java 并发——线程 (2)

java.util.concurrent.Executors

public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter<T>(task, result); } /** * A callable that runs given task and returns given result */ static final class RunnableAdapter<T> implements Callable<T> { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } } 结论:

FutureTask 实现了 RunnableFuture 接口,而 RunnableFuture 继承了 Runnable 和 Future 接口。 这样应证了之前的猜想 —— FutureTask 实现了 Runnable 接口。

FutureTask 有一个 Callable 的域 callable。FutureTask 有两个构造方法,一个传入 Callable ,赋值给了域, 另一个一个传入 Runnable, 最终调用 Executors.callable() 方法,返回了一个 Callable 对象,并且 Call 方法,调用的就是 run 方法。再讲 callable 对象赋值给了域。且两个构造方法的参数都使用了 @NotNull 修饰。

FutureTask 最后调用的 run 方法,实际又是调用的域 Callable 对象的 call 方法。这就是面向对象中的多态的思想,熟悉设计模式的同学也应该能看出来,这里真是适配器模式的实现。最后通过 FutureTask 的 get 方法可以获取线程体执行后的返回值。
使用形式:

new Thread(new FutureTask(new Callable(){ @override public void call(){ xxx } })).start();

或者

new Thread(new FutureTask(new Runnable(){ @override public void run(){ xxx } },"hello,world")).start();

看过源码之后,我感觉这第二种方式一般不建议写,除非返回的结果跟线程体执行无关。FutureTask 表示的计算如果是通过 Callable 来实现额,相当于一种可生成结果的 Runnable ,并且可以处于 3 中状态:运行等待、正在运行、运行完成。 其中运行完成包括可能的结束方式,正常运行,由于取消而结束和由于异常而结束等。当FutureTask处于运行完成状态后,它会永远停止在这个状态。

需要注意的是: Future.get 这个方法取决于任务的状态。如果任务已经完成,那么 get 立即返回结果。否则 get 将阻塞知道任务进入完成状态,然后返回结果或者抛出异常。 FutureTask 保证将计算结果从执行计算的线程安全地发布到获取这个结果的线程。

三、线程池 使用线程池来管理线程

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjpws.html