精华内容
下载资源
问答
  • java中Future的实现原理

    2021-05-07 01:21:11
    文章目录执行结果是如何通过Future返回的Callable是如何被...import java.util.concurrent.Executors; import java.util.concurrent.Future; public class FutureStudy { public static void main(String[] args) {

    执行结果是如何通过Future返回的

    首先我们通过一段代码来看看我们拿到的future对象到底是个什么
    上代码:

    package com.jswdwsx;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class FutureStudy {
    
        public static void main(String[] args) {
            Future<Integer> f = Executors.newSingleThreadExecutor().submit(() -> 1);
    		// 打印返回的future对象的具体类
            System.out.println(f.getClass());
        }
    }
    

    输出如下

    class java.util.concurrent.FutureTask
    

    由运行结果可以看出我们拿到的Future对象的具体类是FutureTask。
    那么我们基于JDK1.8看FutureTask中get方法的实现:

        /**
         * @throws CancellationException {@inheritDoc}
         */
        public V get() throws InterruptedException, ExecutionException {
            int s = state;
            if (s <= COMPLETING)
                s = awaitDone(false, 0L);
            return report(s);
        }
    
        /**
         * @throws CancellationException {@inheritDoc}
         */
        public V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException {
            if (unit == null)
                throw new NullPointerException();
            int s = state;
            if (s <= COMPLETING &&
                (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
                throw new TimeoutException();
            return report(s);
        }
    

    report方法如下:

        /**
         * Returns result or throws exception for completed task.
         *
         * @param s completed state value
         */
        @SuppressWarnings("unchecked")
        private V report(int s) throws ExecutionException {
            Object x = outcome;
            if (s == NORMAL)
                return (V)x;
            if (s >= CANCELLED)
                throw new CancellationException();
            throw new ExecutionException((Throwable)x);
        }
    

    总的来说就是根据state变量判断任务是否执行完成(包括正常和异常),如果未完成就等,正常完成就返回结果,其他情况抛出对应异常。这里的结果—— outcome从何而来,下一节分析。

    Callable是如何被执行的

    我们知道Thread只能执行实现了Runnable接口的任务,那么Callable是如何被执行的呢?
    我们可以查看submit方法源码,这个submit方法是在ExecutorService接口中声明的,在AbstractExecutorService抽象类中实现的。
    几个关键类的继承体系
    上代码:

        public <T> Future<T> submit(Callable<T> task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task);
            execute(ftask);
            return ftask;
        }
    
        protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
            return new FutureTask<T>(callable);
        }
    

    可以看到在submit方法中以task为参数构造了一个FutureTask对象,然后以此为参数调用execute方法,最后返回该对象。
    看到这里我们可以敏锐地察觉到,这个FutureTask类,必然同时实现Runnable接口和Future接口。因为它作为execute方法的参数,而execute方法只接收Runnable对象;同时它作为submit方法的返回值,而submit方法的返回值就是一个Future对象。
    继续看FutureTask类源码:

    public class FutureTask<V> implements RunnableFuture<V> {
    	
    	//...省略其他
    	private volatile int state;
    	private Callable<V> callable;
        private Object outcome;
        private volatile Thread runner;
        
        // 构造方法需要一个Callable作为执行的内容
        public FutureTask(Callable<V> callable) {
            if (callable == null)
                throw new NullPointerException();
            this.callable = callable;
            this.state = NEW;       // ensure visibility of callable
        }
        
        public void run() {
        	// 如果判断状态不是NEW 或者 通过一次CAS设置当前线程为本任务的执行线程失败
            if (state != NEW ||
                !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                             null, Thread.currentThread()))
                return;
            try {
                Callable<V> c = callable;
                if (c != null && state == NEW) {
                    V result;
                    boolean ran;
                    try {
                    	// 这里执行callable的call方法,之后result会被赋值给outcome
                        result = c.call();
                        ran = true;
                    } catch (Throwable ex) {
                        result = null;
                        ran = false;
                        setException(ex);
                    }
                    if (ran)
                        set(result);
                }
            } finally {
                // runner must be non-null until state is settled to
                // prevent concurrent calls to run()
                runner = null;
                // state must be re-read after nulling runner to prevent
                // leaked interrupts
                int s = state;
                if (s >= INTERRUPTING)
                    handlePossibleCancellationInterrupt(s);
            }
        }
        protected void set(V v) {
            if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            	// 这里通过自旋给outcome赋值,回答了上一节最后的问题
                outcome = v;
                UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
    			// 唤醒其他等待线程,并清空等待队列,做一些后续处理工作,就不进去细看了
                finishCompletion();
            }
        }
        //...省略其他(包括前面看过的get和report方法)
    }
    

    RunnableFuture接口源码:

    public interface RunnableFuture<V> extends Runnable, Future<V> {
        /**
         * Sets this Future to the result of its computation
         * unless it has been cancelled.
         */
        void run();
    }
    

    可以看到FutureTask实现了RunnableFuture接口,而RunnableFuture接口继承了Runnable和Future两个接口。
    再看上面FutureTask的run方法,就是执行了通过构造参数参数传入的Callable对象的call方法,并把结果赋值给outcome变量。
    所以Thread是执行了FutureTask的run方法,而FutureTask的run方法执行了Callable的call方法。

    总结Callable任务的执行流程

    可以看到FutureTask类在Callable任务的执行中扮演着十分重要的角色,正是FutureTask将三个关键的部分联系起来:

    • Callable接口(作为构造方法的参数和成员变量)
    • Runnable接口(间接实现)
    • Future接口(间接实现)

    至此我们可以梳理出Callable任务的执行流程:

    1. 我们通过实现Callable接口定义一个带返回值的任务
    2. 通过线程池submit方法提交Callable对象
    3. submit方法构造FutureTask交给线程池执行,同时返回FutureTask用于结果的获取
    4. 线程池将FutureTask交给线程执行
    5. 线程执行FutureTask的run方法
    6. FutureTask的run方法执行Callable对象的call方法,并将结果保存在outcome中
    7. 我们通过返回的FutureTask获取outcome中执行结果
    展开全文
  • Java中提供了很多集合类,这些集合类的数据结构不一样,因此在存储和遍历时的方式不一样。迭代器抽象出集合类的共有功能,提取判断功能和获取功能,得到接口,这个接口就是迭代器接口。在具体子类中实现迭代器接口中...

    Java中提供了很多集合类,这些集合类的数据结构不一样,因此在存储和遍历时的方式不一样。迭代器抽象出集合类的共有功能,提取判断功能和获取功能,得到接口,这个接口就是迭代器接口。在具体子类中实现迭代器接口中的若干方法(使用内部类实现这若干个方法)。接下来分析迭代器的原理和源码。

    首先查看Collection接口的API。

    a16ca1560551

    该接口有一个父接口Iterable,该接口中有一个方法:

    a16ca1560551

    接口中的这个方法返回类型是Iterator类型的接口。继续查看Iterator接口。有三个方法。

    a16ca1560551

    因此,此时的接口体系结构如下:

    a16ca1560551

    在此我们可以发现,最终的子类ArrayList要实现最初的Iterable接口,即实现三个抽象方法(还有一个remove()方法)。我们接下来查看ArrayList类的源码:

    a16ca1560551

    首先在Iterator()方法中返回了一个 new Itr(),说明返回了一个实现类的对象。上图蓝底标记处,就是这个实现类。在此,我们得出最后的体系结构:

    a16ca1560551

    a16ca1560551

    现在,我们可以理解,在

    Collection c = new ArrayList();

    Iterator it = c.iterator()

    这两行代码中,第二行代码的左边是接口,右边是具体类实例对象,再转到第一行,右边是ArrayList的实例,即运行时是ArrayList的实例,因此最终返回的就是ArrayList类中的内部类Itr的实例对象。

    以上就是Java迭代器的源码解析,看起来比较复杂,但是熟练地掌握了接口继承体系结果,内部类,多态(编译看左边,运行看右边)等基本知识,就可以理解迭代器这一机制的原理了。

    展开全文
  • 摘要:利用9个问题帮助记忆流程控制语句中的Java原理知识。
    摘要:利用9个问题帮助记忆流程控制语句中的Java原理知识。

    本文分享自华为云社区《流程控制语句知识点里的java原理》,作者:breakDraw 。

    相信大家经常会遇到这种问题

    可是这个知识点是为什么呢? 我继续以问题的形式来记忆这个问题中的原理。

    Q: 什么是操作数栈
    A:可以理解为jvm做计算时,需要一个临时的寄存器,把需要计算的数据或者传方法的参数放到栈中,然后做计算。

    Q: 什么是栈帧?
    A: 每个线程有一个自己的栈帧,然后运行到每个方法时,每个方法中都会可以理解为是摄影里的一帧。

    Q: 栈帧里包含什么?
    A:

    • 局部变量表
    • 操作数栈
    • 动态链接
    • 方法返回地址

    Q: 栈帧的大小什么时候确定?
    A:在编译程序代码的时候

    Q: 什么是局部变量表?
    A:每个线程所在栈帧都会有一个自己的局部变量表,里面存储方法中使用到的局部变量。

    Q: 实例方法(就是某new出来的对象调用的某个方法)局部变量表的第一个变量是什么?
    A:是this引用。
    因此在实例方法(即非静态方法)中调用f()时, 实际上调用的是this.f(), 而这个this就来自局部变量表。

    PS:

    • returnAddress类型是为字节码指令jsr、jsr_w和ret服务的,它指向了一条字节码指令的地址。
    • 局部变量表的容量以变量槽(Slot)为最小单位,32位虚拟机中一个Slot可以存放一个32位以内的数据类型(boolean、byte、char、short、int、float、reference和returnAddress八种)

    Q:为什么java中局部变量没有默认初始?
    A:我的理解,局部变量在局部变量表中,而局部变量表是运行时生成的, 因此没法在编译期去生成他的默认初始,所以必须通过赋值指令在运行时给他赋值。(没找到很好的解释,有更好理解的可以帮忙回答一下)

    Q:某个方法中执行return a时, 操作数栈和局部变量表会如何变化?
    A:a的值会被放到操作数栈的栈顶,后面取返回值时,就从这里取(即jvm总得知道返回值放哪,而return肯定是方法的最后一步操作,于是默认栈顶)

    Q:在return a之后, 如果在finally操作又对a执行a=2+b, 操作数栈和局部变量表又会如何变化?
    A:原先准备返回的值会被作为局部变量存起来, 接着为了做计算,会取出a和b放到操作数栈中做计算

    而在finally计算结束后,之前存的返回值会被放回栈顶。

    因此,finally里对返回变量的修改,无法修改真正的返回值。
    除非在finally里再执行return操作,这时候就会更改返回值。

    点击关注,第一时间了解华为云新鲜技术~

    展开全文
  • 前面给大家介绍了一下什么是java反射机制,那么下面要给大家介绍的就是java反射机制的原理,那么它的原理究竟是怎样的呢?下面就通过下面来做一下详细的了解吧。首先我们再来介绍一下java反射机制。java反射机制就是...

    前面给大家介绍了一下什么是java反射机制,那么下面要给大家介绍的就是java反射机制的原理,那么它的原理究竟是怎样的呢?下面就通过下面来做一下详细的了解吧。

    首先我们再来介绍一下java反射机制。

    java反射机制就是java程序在运行的时候动态的创建类并调用类的方法以及属性。

    下面就来介绍一下原理。

    一、java反射机制原理

    下面是我们经常可以见到的反射例子:Class

    > clz = Class.forName("java.util.ArrayList");

    ArrayList object = (ArrayList) clz.newInstance();

    Method method = clz.getMethod("add",Object.class);

    method.invoke(list , "sss");

    来分析一下:

    前面的2行实现了类的装载、链接、初始化。

    后面的2行实现了从class对象当中,获取对象,之后执行反射调用。

    这里的话让我们来设想一下,如果,要实现Invoke方法,那么是不是只要实现下面的类就可以了呢?public class Method

    {

    public void invoke(Object obj, Object...args)

    {

    ArrayList list = (ArrayList) obj;

    list.add(args);

    }

    }

    反射的原理之一就是动态的生成类似上面的字节码,加载到jvm当中运行。

    再一起来看看Method对象流程。

    上面的Class对象是在加载类的时候,由jvm构造的。

    jvm为每一个类管理一个独一无二的Class对象,这个Class对象里维护着这个类的所有

    Method、Field、Constructor的cache,这份cache可以被叫做是根对象,每一次,getMethod获取到的Method对象都持有对根对象的引用。

    由于一些重量级的Method的成员变量,大多数都不希望每次在创建Method对象的时候,都要重新进初始化,所以,所有代表同一个方法的Method对象都共享着根对象的MethodAccessor,每一次创建都会调用根对象的copy方法复制一份。Method copy()

    {

    Method res = new Method(clazz, name, parameterTypes, returnType

    , exceptionTypes, modifiers, slot, signature

    , annotations, parameterAnnotations, annotationDefault);

    res.root = this;

    res.methodAccessor = methodAccessor;

    return res;

    }

    调用invoke方法流程

    首先的话,method.invoke方法会获取一个MethodAccessor。

    会先从Method的根对象当中获取MethodAccessor。

    假如是空,那么用reflectionFactory.newMethodAccessor返回DelegatingMethodAccessorImpl实例。

    之后再把MethodAccessor赋值给Method的root对象当中,之后调用DelegatingMethodAccessorImpl当中的invoke方法。

    在调用invoke的次数大于15次之后,MethodAccessor将由java代码生成。

    关于java反射机制原理就给你介绍到这里了,更多java反射机制常见问题,可以继续关注本站来了解。

    推荐阅读:

    展开全文
  • 实现原理 以下文代码为例: public class LambdaTest { @FunctionalInterface public interface LambdaDemo{ public void runLambda(); } public static void doSomething(LambdaDemo demo){ demo.runLambda(); } ...
  • JavaAgent原理及实践

    2021-01-14 10:45:41
    Java Agent是什么? java agent本质上可以理解为一个jar包插件,这个jar包通过JVMTI(JVM Tool Interface)完成加载,最终借助JPLISAgent(Java Programming Language Instrumentation Services Agent)完成对目标...
  • java for循环的解释

    2021-02-12 20:43:06
    展开全部java for循环就是,对于某些操作,人为地控制循环次数。最简单的,比如打印e68a84e8a2ad62616964757a686964616f31333337623536数字。举例:打印 0 ~ 100for(inti=1;i<=100;i++){System.out.println(i);}在...
  • JAVA线程池原理详解一

    千次阅读 2021-03-02 10:55:19
    2047) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369) at test.ThreadTest.main(ThreadTest...
  • java反射的原理、作用

    2021-04-09 11:11:07
    1.什么是反射,反射原理java反射的原理:java类的执行需要经历以下过程,编译:.java文件编译后生成.class字节码文件加载:类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区...
  • Java上传下载文件原理

    2021-02-13 00:29:24
    在工作中常碰到需要上传下载文件的需求,...后台程序通过获取request中的输入流来解析出文件,然后通过outputStream保存在服务器上,这就是Java上传文件的原理。在页面上发送请求下载文件,程序通过inputStream读...
  • Java Future的实现原理

    2021-02-12 19:54:37
    在开发异步任务的时候,为了实现类似java Future模式的能力,对实现方式考量了好久,最终使用了信号量这么重的东西来实现了Future的能力,同时也不禁对java的Future实现产生兴趣,java的Future是怎么...
  • 深入解读Quartz的原理

    2021-03-08 19:38:52
    Quartz是一个大名鼎鼎的Java版开源定时调度器,功能强悍,使用方便。一、核心概念Quartz的原理不是很复杂,只要搞明白几个概念,然后知道如何去启动和关闭一个调度程序即可。1、Job表示一个工作,要执行的具体内容。...
  • JAVA 同步实现原理

    千次阅读 2021-03-08 09:21:19
    原标题:JAVA 同步实现原理Synchronized的基本使用Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。Synchronized的作用主要有三个:确保线程互斥的访问同步代码保证共享变量的修改能够...
  • java实验报告实验原理java实验报告实验原理篇一:java实验报告完整版实 验 报 告(计算机与信息工程学院实验中心)学 期: 2014-2015课程名称: 《Java程序设计实验》班 级: 信息1202 姓 名: 方逸梅 学 号: ...
  • 1.类 简化示例属于java.math包,因此包含各种数学运算,abs,pow等等。package java.math;public class BigDecimal {//值的绝对long型表示private final transient long intCompact;//值的小数点后的位数private final...
  • javaagent技术原理

    2021-12-10 20:55:37
    说道Javaagent是最近经常在使用这个技术,顺便了解了原理与根源,实际上就是jvm开个代理字节码修改的instrument接口。但实际上使用,根据使用的方式不同而略有区别。 1. Javaagent使用 实际上,笔者在前段时间写...
  • 需要编写三类:ComputeTime.java,Plane.java,Car007.java和接口Common.java,要求在未来如果增加第3种交通工具的时候,不必修改以前的任何程序,只需要编写新的交通工具的程序。其运行过程如下,从命令行输入...
  • Java反射机制实现原理

    2021-02-28 13:36:17
    我想考考大家,问大家一个问题:在运行时,你能知道一个JAVA类的属性和方法吗;你能调用它的任何方法吗?---嘿嘿,答案是肯定的,JAVA提供了反射机制可以实现。反射是Java可以提供的一个灵活又强大的功能。使用Java...
  • JAVA强制类型转换原理

    2021-01-15 14:15:19
    强制转换原理 比如 Long类型转换为int类型 原始数据(long)00000000 00000000 00000000 00000000 00000000 00000000 00000000 01100100 强制转换后的数据: 00000000 00000000 00000000 01100100
  • java之fork-join原理

    千次阅读 2021-04-13 22:06:32
    目录 使用示例 ForkJoin原理 数据结构 使用示例 ForkJoin使用场景主要是并行计算,将大任务不断拆分,拆分成足够小任务,多线程并行运算,最后汇总结果。 fork-join在任务计算耗时比较长的时候,进行拆分是比较划算...
  • java 缓冲流+原理图解

    2021-03-16 19:22:56
    java 缓冲流什么是java缓冲流?缓冲流也叫高效流,是对四个基本的FileXxx流的增强,按照数据类型分类:字节缓冲流 :BufferedInputStream,BufferedOutputStream字符缓冲流:BufferedReader,BufferedWriter基本原理...
  • Java Stream 底层原理

    千次阅读 2021-11-13 19:11:41
    你可能没意识到Java对函数式编程的重视程度,看看Java 8加入函数式编程扩充多少功能就清楚了。Java 8之所以费这么大功夫引入函数式编程,原因有二: 代码简洁函数式编程写出的代码简洁且意图明确,使用_stream_接口...
  • java的JIT 工作原理简单介绍1.JIT的工作原理图工作原理当JIT编译启用时(默认是启用的),JVM读入.class文件解释后,将其发给JIT编译器。JIT编译器将字节码编译成本机机器代码。通常javac将程序源代码编译,转换成java...
  • 揭秘Java虚拟机 JVM设计原理与实现 内容简介《揭秘Java虚拟机:JVM设计原理与实现》从源码角度解读HotSpot的内部实现机制,本版本主要包含三大部分——JVM数据结构设计与实现、执行引擎机制及内存分配模型。...
  • 1、原理:当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。例如:创建一个“人”类Class Person人拥有吃的方法public void eat(){},我们的目的就是,在这个人吃之前要提醒他洗手,所以我们就要...
  • 上一篇文章《java8 stream运行原理之顺序流原理详解》介绍了顺序流的执行原理,本文接着上一篇介绍并行流的执行原理。 一、如何创建并行流 调用parallel()方法可以创建并行流,如下: public static void main...
  • JAVA跨平台原理详细介绍 一、Java虚拟机是什么? Java虚拟机(Java Virtual Machine,简称 JVM) JAVA的核心机制有两个:跨平台机制(JAVA虚拟机),垃圾回收机制 二、JAVA跨平台机制实现了:一次编译,到处运行 ...
  • 本书全面系统地讲解了Java并发实现原理,从基础的多线程知识讲起,全面介绍了Concurrent包的每个部分,详细分析多线程背后的原理,同时从源码角度进行了剖析,为的一本好书。本书全面而系统地剖析了Java Concurrent...
  • java 监听器实现原理

    2021-03-10 05:12:06
    监听器实现者:public class MyActivity extends Activity implements InternetManager.Listener {private TextView mText;private InternetManager mInetMgr;/* called just like onCreate at some point in time *...
  • java懒加载的原理

    千次阅读 2021-03-17 22:27:37
    Java 2008-07-26 08:50:53 阅读 267 评论 0 字号:大中小 JSP 的工作原理--- ---精 品 word 文档 值得下载 值 得拥有--- --- --- --- --- ...... Java Web 开发技术试题 1.(单选题)使用 JDBC 访问数据库时,下列... ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,173,628
精华内容 469,451
关键字:

java原理

java 订阅