Java并发编程-Executor框架之Callable和Future接口

在上一篇文章中我们已经了解了Executor框架进行线程管理,这篇文章将学习Executor框架的另一个特性,我们知道执行Runnable任务是没有返回值得,但Executor可以运行并发任务并获得返回值,Concurrent包提供下面两个接口实现这个功能:

  • Callable接口:这个接口声明call()方法类似于Runnable的run()方法,可以在这个方法里实现任务的具体逻辑操作。Callable是一个泛型接口,必须声明call()的返回类型。

  • Future接口:这个接口声明了一下方法来获取Callable的返回数据。

使用方法

通过Executor的submit()提交Callable任务执行,这个Submit()方法将会返回Future对象。利用Future对象可以

  • 使用isDone()方法,查看任务是否完成。

  • 通过get()方法获call()方法执行的返回值,这个方法会一直等待callable对象执行完call()方法并返回结果。如果出现中断,get()方法会抛出InterruptedException,或者call()方法抛出的异常。

  • get(long timeout,TimeUnit unit):该方法设置等待时间timeout,如果等待超过了指定的时间而任务的结果还没准备好,那么这个方法将返回null

使用实例:

package MyThread;

import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

public class ExecutorTest {
    public static void main(String[] args){
        ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
        ArrayList<Future<String>> list=new ArrayList<>();
        for (int i = 0; i < 5; i++){
            //Future和每个线程关联
            Future<String> result=executor.submit(new task()); 
            list.add(result);           
        }
        //遍历Future,获取返回值
        for(Future<String> f:list){
            try {
                //while(!f.isDone()){};
                //阻塞等待获取返回值
                System.out.println(f.get());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        executor.shutdown();

    }

}
//定义Callable实现类,返回一个字符串
class task implements Callable<String>{
    @Override
    public String call() throws Exception {
        // TODO Auto-generated method stub
        Random random=new Random();
        int result=random.nextInt(100);
          // 第二阶段——等待所有选手准备好
        Thread.sleep((long) (random.nextInt(5) * 1000)); 
        return Thread.currentThread().getName()+":"+result;
    }

}

结果:
pool-1-thread-1:84
pool-1-thread-2:78
pool-1-thread-3:15
pool-1-thread-4:99
pool-1-thread-5:2

运行多个任务并处理所以结果:
ThreadPoolExecutor通过一个 invokeAll()方法,支持将多个Callable任务放进集合当中,并等待所有任务完成,再把结果返回到Future的链表当中。

与submit()不同,invokeAll()会阻塞直到所以得任务都执行完成。
例如:

package MyThread;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

public class ExecutorTest {
    public static void main(String[] args){
        ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();

        //任务链表
        List<task> tasklist=new ArrayList<>();
        //结果链表
        List<Future<String>> resultlist=new ArrayList<>();
        for (int i = 0; i < 5; i++){            
            tasklist.add(new task());           
        }
        try {
            resultlist=executor.invokeAll(tasklist);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } 

        System.out.println("获取执行结果:");
        for(Future<String> f:resultlist){
            try {
//              while(!f.isDone()){};           
                System.out.println(f.get());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        executor.shutdown();

    }

}
class task implements Callable<String>{
    @Override
    public String call() throws Exception {
        // TODO Auto-generated method stub
        Random random=new Random();
        int result=random.nextInt(100);
          // 第二阶段——等待所有选手准备好
        Thread.sleep((long) (random.nextInt(5) * 1000)); 
        return Thread.currentThread().getName()+":"+result;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值