java併發編程(五)CompletionService

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得到的值。但在使用時需要根據計算的任務迭代得到值。這個非常重要。否則程序直接跳過,只能得到最先獲取的值。突然想到,如果有一個任務,可以由多種不同的方法計算出結果。這個方法倒是一個較好的選擇。即只要程序得到第一個結果,後面就可以放棄,不用管它。程序繼續向下運行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章