一、invokeAny()方法
作用:取得第一个完成任务的结果值,当第一个任务执行完成后,会调用interrupt方法将其他的任务中断。
在这里会出现两种情况:
- 无 Thread.currentThread().isInterrupted() 的判断,则已经获得第一个运行的结果的值后,其他线程继续运行;
- 有 Thread.currentThread().isInterrupted() 的判断,再结合new InterruptedException使得这些线程中断;
例子如下:
package invoke;
import java.util.concurrent.Callable;
/**
* @Author: jiaqing.xu@hand-china.com
* @Date: 2019-04-07 21:41
* @Description
*/
public class MyCallableA implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("CallableA begin:" + System.currentTimeMillis());
for (int i = 0; i < 1000; i++) {
System.out.println("A:" + i);
}
System.out.println("CallableA end:" + System.currentTimeMillis());
return "call A";
}
}
package invoke;
import java.util.concurrent.Callable;
/**
* @Author: jiaqing.xu@hand-china.com
* @Date: 2019-04-07 21:43
* @Description
*/
public class MyCallableB implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("CallableB begin:" + System.currentTimeMillis());
for (int i = 0; i < 1000; i++) {
System.out.println("B:" + i);
}
System.out.println("CallableB end:" + System.currentTimeMillis());
return "call B";
}
}
package invoke;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @Author: jiaqing.xu@hand-china.com
* @Date: 2019-04-07 21:46
* @Description
*/
public class RunMain1 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(new MyCallableA());
list.add(new MyCallableB());
ExecutorService executorService = Executors.newCachedThreadPool();
try {
String getValueA = (String) executorService.invokeAny(list);
System.out.println(getValueA);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
结果不会因为A的invokeAny而导致,B的终止:
但是,如果将MyCallableB改造成如下形式:
import java.util.concurrent.Callable;
/**
* @Author: jiaqing.xu@hand-china.com
* @Date: 2019-04-07 21:43
* @Description
*/
public class MyCallableB implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("CallableB begin:" + System.currentTimeMillis());
for (int i = 0; i < 1000; i++) {
if (!Thread.currentThread().isInterrupted()) {
System.out.println("B:" + i);
} else {
System.out.println("开始抛出异常...");
throw new InterruptedException("异常");
}
}
System.out.println("CallableB end:" + System.currentTimeMillis());
return "call B";
}
}
A线程会正常执行完毕,但是B线程会因为A的invokeAny而终止执行:
二、invokeAll()方法
作用:返回所有任务的执行结果,该方法的执行效果也是阻塞执行的,要把所有的结果都取回时再继续向下执行。
MyCallableA等待3s:
package invoke;
import java.util.concurrent.Callable;
/**
* @Author: jiaqing.xu@hand-china.com
* @Date: 2019-04-07 21:41
* @Description
*/
public class MyCallableA implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("CallableA begin:" + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("CallableA end:" + System.currentTimeMillis());
return "call A";
}
}
MyCallableB等待5s:
package invoke;
import java.util.concurrent.Callable;
/**
* @Author: jiaqing.xu@hand-china.com
* @Date: 2019-04-07 21:43
* @Description
*/
public class MyCallableB implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("CallableB begin:" + System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("CallableB end:" + System.currentTimeMillis());
return "call B";
}
}
package invoke;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @Author: jiaqing.xu@hand-china.com
* @Date: 2019-04-07 22:06
* @Description
*/
public class RunMain2 {
public static void main(String[] args) throws InterruptedException {
MyCallableA myCallableA = new MyCallableA();
MyCallableB myCallableB = new MyCallableB();
List<Callable<String>> callableList = new ArrayList<>();
callableList.add(myCallableA);
callableList.add(myCallableB);
ExecutorService executorService = Executors.newCachedThreadPool();
//开始时间
Long startTime = System.currentTimeMillis();
System.out.println("invoke all begin: " + startTime);
//invokeAll等到两个线程的返回 它是阻塞的
List<Future<String>> futureList = executorService.invokeAll(callableList);
//结束时间
Long endTime = System.currentTimeMillis();
System.out.println("invoke all end: " + endTime);
//输出最后的耗时
System.out.println("all time: " + (endTime - startTime) / 1000 + "s");
}
}