JAVA多线程-交互计算 Future Callable Promise

前篇:

JAVA多线程-基础Synchronized
JAVA多线程-基础Lock Condition 并发集合

完成前面两篇文章的代码训练后,继续往深层进发. 线程的编程模式打破了传统的代码顺序执行的习惯. 两个线程之间的交互也改变了原来的调用-返回值模式. 同样的,javascript的ajax callback方式也有着同样的痛苦. 为了让程序员保留原来的编程习惯,也为了让代码逻辑更容易读懂. 多线程计算提供了两种模式: Future和Promise.

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

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);
        }
    }
}


你可能感兴趣的:(java,thread,多线程,Promise,future)