> 文档中心 > 线程池+Callable+FutureTask实现多线程

线程池+Callable+FutureTask实现多线程

关于线程池就不做太多介绍,相关文章有很多,本文重点是记录自己测试线程池+Callable+FutureTask实现多线程的代码,大家可以参考参考;

public class threadPoolTestService {    public void test(){ //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(5); //线程安全的AtomicInteger,后续多线程减少数据 AtomicInteger atomicInteger = new AtomicInteger(20); //创建一个线程安全的集合 CopyOnWriteArrayList<FutureTask> integers = new CopyOnWriteArrayList(); //记录一个开始时间 long start = System.currentTimeMillis(); //for循环调用多线程执行任务 for (int i = 0; i < 10; i++) {     //返回结果是异步的,线程执行,就会返回,只不过没有具体数据     FutureTask integerFutureTask = new FutureTask(new Callable() {  @Override  public Integer call() throws Exception {      System.out.println(Thread.currentThread().getName() + "--------");      //方法执行2s      Thread.sleep(2000);      //数据减1      return atomicInteger.getAndDecrement();  }     });     //执行任务     executorService.submit(integerFutureTask);     //封装结果     integers.add(integerFutureTask); } //处理多线程执行的结果集 for (FutureTask integer : integers) {     try {  //注意,futureTask的get方法,会导致线程阻噻,也就会等待任务执行完毕,获取结果  System.out.println(integer.get());     } catch (InterruptedException e) {  e.printStackTrace();     } catch (ExecutionException e) {  e.printStackTrace();     } } long end = System.currentTimeMillis(); System.out.println("耗时:"+(end-start));    }}

控制台输出:

 显然,总共有5个线程工作,数字从20减到11;

注意:Future和FutureTask的get()方法,是会阻塞的,如果上述部分代码更改成如下所示(在for循环里面调用了FutureTask.get()方法)

//集合更改为Integer类型,不再是FutureTask类型CopyOnWriteArrayList integers = new CopyOnWriteArrayList(); //记录一个开始时间 long start = System.currentTimeMillis(); //for循环调用多线程执行任务 for (int i = 0; i < 10; i++) {     //返回结果是异步的,线程执行,就会返回,只不过没有具体数据     FutureTask integerFutureTask = new FutureTask(new Callable() {  @Override  public Integer call() throws Exception {      System.out.println(Thread.currentThread().getName() + "--------");      //方法执行2s      Thread.sleep(2000);      //数据减1      return atomicInteger.getAndDecrement();  }     });     //执行任务     executorService.submit(integerFutureTask);     //封装结果,调用get()方法     integers.add(integerFutureTask.get()); }

结果将变成

 显然,耗时20040比原来的4016要大很多,虽然输出里面显示有5个线程在工作,但是都是等上一个线程执行结束,下一个线程才开始执行,基本就和单线程无异了;

这是因为我们在for循环里面调用了FutureTask.get()方法,该方法会等待当前线程把代码执行完拿到返回结果才终止;而我们开启下一个线程的前提是当前循环结束,进入下一次循环才会开启新的线程;这样新线程开启的时候,上一个线程都已经完全执行结束了,所以就和单线程无异了,导致耗时很长;