多線程之callable學習

最近在看多線程方面的內容,注意到java中原來除了Runnable和Thread以外還有Callable的方式實現多線程,而且Callable還能獲得子線程的返回值,這是前面兩種方式所不具備的。java

  Callable是一個藉口,而且支持泛型,咱們編寫多線程只須要實現這個接口,而且重寫call方法,要獲得Callable的返回值就要使用Future對象,Callable負責計算結果,Future負責拿到結果,具體的使用請看以下兩個例子:web

public class CallableAndFuture {
    public static void main(String[] args) {
        Callable<Integer> callable = new Callable<Integer>() {
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        };
        FutureTask<Integer> future = new FutureTask<Integer>(callable);
        new Thread(future).start();
        try {
            Thread.sleep(5000);// 可能作一些事情
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

上面例子是經過Thread來包裝FutureTask來啓動線程,FutureTask實現了兩個接口,Runnable和Future,因此它既能夠做爲Runnable被線程執行,又能夠做爲Future獲得Callable的返回值,那麼這個組合的使用有什麼好處呢?假設有一個很耗時的返回值須要計算,而且這個返回值不是馬上須要的話,那麼就能夠使用這個組合,用另外一個線程去計算返回值,而當前線程在使用這個返回值以前能夠作其它的操做,等到須要這個返回值時,再經過Future獲得,豈不美哉!多線程

下面來看另外一種方式使用Callable和Future,經過ExecutorService的submit方法執行Callable,並返回Future,代碼以下:dom

 

public class CallableAndFuture {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        Future<Integer> future = threadPool.submit(new Callable<Integer>() {
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        });
        try {
            Thread.sleep(5000);// 可能作一些事情
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

 

  執行多個帶返回值的任務,並取得多個返回值,代碼以下:spa

public class CallableAndFuture {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool);
        for(int i = 1; i < 5; i++) {
            final int taskID = i;
            cs.submit(new Callable<Integer>() {
                public Integer call() throws Exception {
                    return taskID;
                }
            });
        }
        // 可能作一些事情
        for(int i = 1; i < 5; i++) {
            try {
                System.out.println(cs.take().get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}
相關文章
相關標籤/搜索