天天看点

java线程实现

java线程实现

2.实现runnable接口,实现其run()方法,创建其实例,并通过该实例构造 thread ,通过thread来启动。

实际执行了我们传入runnable对象的run方法。

3.jdk1.5之后又提供了另一种方式,通过实现callable接口来创建线程,提供有返回值的call方法,来达到获得线程返回值的目的,外部线程可以通过future接口可以获得线程执行结果。

使用callable创建线程的启动方式稍微复杂,代码如下:

从上面可以看到callable和前两种实现方式的差别是callable可以获得返回值。

除了我们手动创建futuretask的方式启动以外,还可以通过jdk提供的并发执行器进行执行,不需要我们自己手动创建futuretask对象来执行,代码如下:

执行器同样可以用来执行runnable对象,代码类似,只是不能获得返回值。

下面看看callable如何做到返回线程执行结果的,首先我们看看futuretask的类继承关系:

java线程实现

从上图可以很清晰的看到futuretask实际也实现了runnable接口 ,其run方法实现如下:

所以可以看出来callable实际就是在runnable进行了一层包装达到可以携带执行返回结果的目的。

所以总结下来,其实后两种实现都是在thread基础上进行封装的,实际的执行都是靠thread对象来执行的。

实际上是调用了本地方法start0()

本地方法,定义在thread.c文件里面

从上面的代码可以看出start0实际是调用了jvm_startthread方法,我们找找jvm_startthread方法的定义

可以看到在jvm_startthread方法里面创建了实际跟平台有关系的本地线程,线程函数是thread_entry ,thread_entry定义了实际调用vmsymbols::run_method_name()这个方法,这个方法实际就是定义运行run方法,在vmsymbols.hpp可以看到定义如下:

本地线程最终执行run_method_name这个方法

可以看到线程最终执行我们的thread对象的run方法。

所以整个调用时序是 thread.start -->jvm_startthread -->thread_entry  --> os本地线程(异步) --> thread.run

从上面我们知道java 线程是建立在系统本地线程之上的,通过thread对象做了一层封装,封装了各个不同平台的细节,提供了统一的api ,thread之上又做了 runnable的回调和callable的回调。

java线程创建和执行的三种方式最终都是通过thread来实现的。

注:本文源码部分来源于jdk1.7和openjdk7源码,可以从下面地址下载。

http://download.java.net/openjdk/jdk7