java多线程[10]:Callable和Future

来源:互联网 发布:好听淘宝名字大全 编辑:程序博客网 时间:2024/06/07 00:45

本篇要讨论的是Callable接口和Future接口。想要创建一个线程的话,除了实现Runnable接口外,还可以实现Callable接口,这样的话,在线程运行结束后可以返回一个运行结果。

在上一篇博客中我们讨论了如何使用线程池来启动线程,并对比了几种不同的线程池之间的差异。ExecutorService的submit方法的定义如下

<T> Future<T> submit(Callable<T> task);

它提交一个实现了Callable接口的类,这个类将作为一个线程异步地运行。submit方法的返回值是一个Future对象,如果想查询这个异步运行着的线程的运行状态或运行结果的话,可以通过这个Future对象来进行。Future接口包含以下方法

//取消任务boolean cancel(boolean mayInterruptIfRunning);//是否已取消boolean isCancelled();//是否已完成boolean isDone();//阻塞并等待线程的返回结果V get() throws InterruptedException, ExecutionException;//阻塞一定时间并等待线程的返回结果。如果超过时间后没有返回结果的话,则抛出TimeoutException异常V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

可以看得出来,Future接口包含了很多有用的方法可以控制或查询线程的运行状态。

下面来看一个例子。假设有一个list共包含从1到100这一百个数字,而我们要计算这一百个数字的和。为了提高计算速度,我将这个list拆分成三个小list并启动三个线程来并行计算他们的和,最终将三个线程返回的和加到一起,从而得到整个list的总和。这个线程要实现Callable接口,这样才能返回一个计算结果。下面是这个实现了Callable接口的类

import java.util.List;import java.util.concurrent.Callable;public class CallableWorker implements Callable<Integer> {    private List<Integer> numberList = null;    public CallableWorker(List<Integer> numberList) {        this.numberList = numberList;    }    @Override    public Integer call() throws Exception {        int total = 0;        for (int number : numberList) {            total += number;        }        return total;    }}

这个类接收一个List<Integer>对象,然后计算这个集合内所有数字的和,并返回这个和。

下面通过一个线程池来启动三个CallableWorker

import java.util.ArrayList;import java.util.List;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class FutureDemo {    public static void main(String[] args) throws ExecutionException, InterruptedException {        List<Integer> list = new ArrayList<>();        for (int i = 1; i <= 100; i++) {            list.add(i);        }        //拆分为三个集合        List<Integer> sublist1 = list.subList(0, 30);        List<Integer> sublist2 = list.subList(30, 60);        List<Integer> sublist3 = list.subList(60, 100);        ExecutorService executorService = Executors.newFixedThreadPool(3);        //启动三个异步线程来分别计算三个集合的和        Future<Integer> future1 = executorService.submit(new CallableWorker(sublist1));        Future<Integer> future2 = executorService.submit(new CallableWorker(sublist2));        Future<Integer> future3 = executorService.submit(new CallableWorker(sublist3));        //汇总三个线程的计算结果        int total = future1.get() + future2.get() + future3.get();        System.out.println("total = " + total);        //关闭线程池,否则进程无法结束        executorService.shutdown();    }}

我使用Executors.newFixedThreadPool(3)创建了一个包含三个线程的线程池,然后将list对象拆分为三个sublist对象并传递给三个CallableWorker。使用executorService.submit()方法提交一个线程,使用future1.get()获取进程的返回结果。

最终求和的结果是5050。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 爱抢购app 爱抢购下载 头部按摩仪 微电脑电炖盅怎么用 led工厂灯具 工厂用灯具 黑灯工厂 洗墙灯工厂 工厂庭院灯 氙气灯工厂 景观灯工厂 工厂照明灯 道路灯生产厂家 防爆工厂灯 工厂照明用灯 车间照明用灯 工厂灯图片 led防爆工厂灯 太阳能灯工厂 工厂led防爆灯 工厂照明用什么灯 车间灯 灯具制造厂 灯具加工厂 led灯具加工厂 工矿照明灯具 防爆工矿灯具 飞利浦工矿灯具 车间照明用什么灯 工厂尾货女装 工厂用货梯价格 工厂用货梯 工厂尾货服装批发 雪可工坊奶茶 减脂叶的功效和作用 工号牌厂家 成都工号牌 铝合金工号牌 金属工号牌 工号牌图片 工号牌