CompletionService可以在多个任务中依时间先后获取最先执行完成的任务结果。废话不说,直接上代码。
import java.util.concurrent.Callable;
public class BlockCall extends Thread implements Callable<String>{
private int blocktime;
public BlockCall(String name,int blocktime) {
super.setName(name);
this.blocktime=blocktime;
}
public String call() throws Exception {
Thread.sleep(blocktime);
return super.getName();
}
}
import java.text.SimpleDateFormat;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestService {
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
final String strformat = "ThreadName:%s %s";
CompletionService service = null;
public static void main(String[] args) throws Exception {
//new TestService().notBlock();
new TestService().block();
}
private void block() throws Exception{
initial();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
int resultCount=0;
while(resultCount<4) {
resultCount++;
Object object = service.take().get();
System.out.println(object+" "+ dateFormat.format(System.currentTimeMillis()));
}
newCachedThreadPool.shutdown();
}
private void notBlock() throws Exception{
initial();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
int resultCount=0;
while(resultCount<4) {
Future poll = service.poll();
Object object = "null ";
if(poll!=null) {
object=poll.get();
resultCount++;
}
Thread.sleep(200);
System.out.println(object+" "+ dateFormat.format(System.currentTimeMillis()));
}
newCachedThreadPool.shutdown();
}
private void initial() {
String[] names = new String[] {"A","B","C","D"};
Integer[] times = new Integer[] {4000,3000,2000,1000};
BlockCall[] calls = new BlockCall[4];
for(int i=0;i<calls.length;i++) {
calls[i] = new BlockCall(names[i],times[i]);
}
service = new ExecutorCompletionService<String>(newCachedThreadPool);
for(int i=0;i<calls.length;i++) {
service.submit(calls[i]);
}
}
}
下面是take方式得到的执行结果。
D 2020-03-29 18:19:03.866
C 2020-03-29 18:19:04.866
B 2020-03-29 18:19:05.866
A 2020-03-29 18:19:06.866
下面是poll方式得到的执行结果。
null 2020-03-29 18:24:45.033
null 2020-03-29 18:24:45.235
null 2020-03-29 18:24:45.435
null 2020-03-29 18:24:45.635
null 2020-03-29 18:24:45.835
D 2020-03-29 18:24:46.035
null 2020-03-29 18:24:46.235
null 2020-03-29 18:24:46.435
null 2020-03-29 18:24:46.635
null 2020-03-29 18:24:46.835
C 2020-03-29 18:24:47.035
null 2020-03-29 18:24:47.235
null 2020-03-29 18:24:47.435
null 2020-03-29 18:24:47.635
null 2020-03-29 18:24:47.835
B 2020-03-29 18:24:48.035
null 2020-03-29 18:24:48.235
null 2020-03-29 18:24:48.435
null 2020-03-29 18:24:48.635
null 2020-03-29 18:24:48.835
A 2020-03-29 18:24:49.035
结论:take和poll都可以获取到Future得到的值。但在使用时需要根据计算的任务迭代得到值。这个非常重要。否则程序直接跳过,只能得到最先获取的值。突然想到,如果有一个任务,可以由多种不同的方法计算出结果。这个方法倒是一个较好的选择。即只要程序得到第一个结果,后面就可以放弃,不用管它。程序继续向下运行。