JAVA多线程-基础Synchronized
JAVA多线程-基础Lock Condition 并发集合
完成前面两篇文章的代码训练后,继续往深层进发. 线程的编程模式打破了传统的代码顺序执行的习惯. 两个线程之间的交互也改变了原来的调用-返回值模式. 同样的,javascript的ajax callback方式也有着同样的痛苦. 为了让程序员保留原来的编程习惯,也为了让代码逻辑更容易读懂. 多线程计算提供了两种模式: Future和Promise.
Promise是多线程的非阻塞模式.但有些类似callback. 它在javascript中得到了很好的应用.比如,dojo.promise. 每一个ajax HTTP request返回一个promise,许诺在ajax线程返回结果以后,运行promise.then()中的代码函数.这样就主线程可以越过then(),继续向下执行,而不用等待ajax线程的返回.
function() { promise = googleRequest(); promise.then(function(result){ handleResult(); }); doOtherWorks(); }function发起googleRequest线程, 线程promise在结果返回以后将执行then()中的代码. function得到promise,安心的去执行doOtherWorks,而不用等待googleRequest的返回了.
dojo.promise.all还可以同时管理多个promise.如下,function发起3个异步请求,3个请求相互独立. all将管理3个promise,一旦3个异步请求全部完成,将执行then中的代码. 主线程function安心的去doOtherWorks,而不用等待异步请求.
function() { promise1 = googleRequest(); promise2 = baiduRequest(); promise3 = taobaoRequest(); all([promise1,promise2,promise3]).then(function(result){ handleRequest(); }); doOtherWorks(); }
Future是多线程计算的一种阻塞模式.假设有两个线程T1, T2. 它们在分别计算两组数据,希望将两个线程分别计算出来的结果相乘,得到最终答案. 存在这么一种模式,使得编程非常直观:
Future1 = T1.compute(); Future2 = T2.compute(); doOtherWorks(); Final = Future1.get()*Future2.get();
非常直观, future1就是存储T1运算结果的地方.同理future2是T2的运算结果.直接调用Future.get()就可以取出结果. T1和T2在运行开始的时候,约定好计算结束的时候把结果放入Future1和Future2.然后就各自去执行计算了,主线程也并不需要等待T1和T2的返回,可以继续执行doOtherWorks(). 只有当调用Future.get()的时候,如果T还没计算完成,那么get()就会阻塞.直到T把结果存储到Future中.
JAVA是如何实现Future模式的?
Java中存在Runnable, Callable, Future接口, FutureTask类. Callable和Runnable相同的作用,Callable使得线程执行call()方法,并将值返回给Future. Future只是一个存储call()值的地方. FutureTask是一个实现了Runnable和Future接口的类, 使用new FutureTask(Callable call)生成一个task线程, 调用task.start()启动线程, 线程调用Callable的call方法,并将值存于task中(task实现了Future). 后面直接调用task.get()来获得线程计算值.
下面给出一个可以运行的JAVA实例. 主线程发起两个支线程,分别计算各自的数值.主线程将两个线程的计算结果相乘,计算最终数值.
package concurrency; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class FutureTest { public static void main(String[] args) throws InterruptedException, ExecutionException { int result = new FutureTest().test(); System.out.println(result); } private int test() throws InterruptedException, ExecutionException { MyCall<Integer> call1 = new MyCall<Integer>("1"); FutureTask<Integer> task1 = new FutureTask<Integer>(call1); new Thread(task1).start(); MyCall<Integer> call2 = new MyCall<Integer>("2"); FutureTask<Integer> task2 = new FutureTask<Integer>(call2); new Thread(task2).start(); return task1.get()*task2.get(); } private class MyCall<T> implements Callable<Integer> { private String name; private MyCall(String name) { this.name = name; } @Override public Integer call() throws Exception { int i=10; while (i>0) { i--; System.out.println("MyCall:["+name+"] is working."); Thread.sleep(1000); } return Integer.valueOf(12); } } }