多线程任务Callable与Future或FutureTask的使用

时间:2021-10-10 18:03:13
  在进行多线程任务时,我们可以使用Thread、Runnable已经java5以后新增的concurrent包内的Callable,Runable跟Thread的用法就不说了,这里要说的是使用Runnable时,如何获取结果以及抛出的异常,这样子很难定位在执行多线程任务时的程序异常。这里推荐使用Callable和Future或者FutureTask配合,获取结果。


简单的使用代码


//Callable实现类

import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;

/**
*
* @author PYY
*
*/
public class CounterThread implements Callable<Integer> {

private CountDownLatch countDownSign;

private String name;

public CountDownLatch getCountDownSign() {
return countDownSign;
}

public void setCountDownSign(CountDownLatch countDownSign) {
this.countDownSign = countDownSign;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public CounterThread(String name) {
this.name = name;
}

@Override
public Integer call() throws Exception {
int result = 0;
try {
System.out.println(name + "正在执行中,准备运算");
result = 3 / (int) (Math.random() * 3);
} catch(Exception e) {
System.out.println(name + "执行异常");
} finally {
countDownSign.countDown();
}
return result;
}

}


1 使用future接口获取

<pre name="code" class="java">ExecutorService service = Executors.newSingleThreadExecutor();
CounterThread counter = new CounterThread("线程" + i);
Future<?> future = service.submit(counter);
service.shutdown();
try {
//睡眠,等待子线程执行完成
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println("查看运行结果:" + future.get());

 

2 使用FutureTask类


ExecutorService service = Executors.newSingleThreadExecutor();
CounterThread counter = new CounterThread("线程" + i);
FutureTask<Integer> task = new FutureTask<Integer>()
service.submit(task);
service.shutdown();
try {
//睡眠,等待子线程执行完成
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println("查看运行结果:" + task.get());


但是在使用多线程时,不可能只使用一个线程,有时我们希望在所有的线程都进行完成后再统一获取结果,这时我们需要一个线程计数器,这里推荐CountDownLatch,不废话,直接上代码


List<Future<?>> taskList = new ArrayList<Future<?>>();
CountDownLatch latch = new CountDownLatch(30);
try {
for(int i = 0; i < 30; i++) {
ExecutorService service = Executors.newSingleThreadExecutor();
CounterThread counter = new CounterThread("线程" + i);
counter.setCountDownSign(latch);
Future<?> future = service.submit(counter);
taskList.add(future);
service.shutdown();
}
//等待线程执行完成,计数器减到0
latch.await();
System.out.println("主线程执行完毕,查询子线程结果");
for(Future<?> task : taskList) {
System.out.println("查看" + task.isDone() + "运行结果:" + task.get());
}
} catch (Exception e) {
System.out.println("异常了");
e.printStackTrace();
}


更多学习  Callable、Future和FutureTask的内容,参考这篇博文

CountDownLatch文章移步这里