最近好好的研究了下future的使用,使用future,callable的作用主要在于异步计算结果并返回,是用于解决并发的方法,以下为我做的一些简单测试,首先定义一个类(可用于封装future的计算结果),

public class Result {
	private Integer code;
	private String msg;
	public Integer getCode() {
		return code;
	}
	public void setCode(Integer code) {
		this.code = code;
	}
	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}	

在定义一个方法实现callable接口

public class threadResult implements Callable<Result>{
	private String  name;
	private int age;
	
	public threadResult() {
		super();
	}

	public threadResult(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public Result call() throws Exception {
		Result res=new  Result();
		res.setCode(age);
		res.setMsg(name);
		System.out.println("call执行时间======="+System.currentTimeMillis()+"name"+name+"=======age"+age);
//		Thread.sleep(2000);
		return res;
	}

然后是我的测试类:

测试方法一

public void doThread(){
		try{
//			FutureTask<Result> futureTask = new FutureTask<Result>(new threadResult());
//	    	ExecutorService executor = Executors.newFixedThreadPool(1);//使用线程池
			ExecutorService executor=new ThreadPoolExecutor(2,2,1000, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardOldestPolicy());
			    //FutureTask<Result> future =(FutureTask<Result>) executor.submit(new threadResult());
			    Future<Result> future=executor.submit(new threadResult("张三",23));
			    Result res=future.get();
			    System.out.println(res.getCode());
			    System.out.println(res.getMsg());
		    executor.shutdown();   
		}catch(Exception e){
	    	e.printStackTrace();
	    }
	}

future的工作流程,如上executor.submit 此处相当于从线程池中取出一个线程然后执行,(new threadResult("张三",23))这一部分相当是调用threadResult的有参构造方法,然后默认会去调用call进行计算,计算完以后会把结果返回给future,输出的结果如下

call执行时间=======1471530865285name张三=======age23

23

张三

当然也可以调用无参的,结果就变成

call执行时间=======1471530946543namenull=======age0

0

null


测试方法二:

public void doThread2(){
try{
 ExecutorService executor = Executors.newFixedThreadPool(3);//使用线程池
for(int i=0;i<10;i++){
Future<Result> future=executor.submit(new threadResult("hello word"+i,i));
Result res=future.get();
 System.out.println(res.getCode()+"=================="+System.currentTimeMillis());
System.out.println(res.getMsg()+"=================="+System.currentTimeMillis());
}
}catch(Exception e){
	 e.printStackTrace();
 }
}

这个其实也没什么特别的地方,这边使用的是固定大小线程池,运行时最大会有三个线程同时运行

测试方法三:

public void doThread3(){
		try{
			List<Future<Result>> futures=new ArrayList<Future<Result>>();
			ExecutorService executor = new ThreadPoolExecutor(2,2,1000, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardOldestPolicy());//使用线程池
			for(int i=0;i<10;i++){
			    futures.add(executor.submit(new threadResult("hello word"+i,i)));
			}
			executor.shutdown(); 
			while(true){
				if(futures.size()==0){;break;}
				System.out.println(1);
				for(Future<Result> future:futures){
			    	 Result res=future.get();
				     System.out.println(res.getCode()+"=================="+System.currentTimeMillis());
				     System.out.println(res.getMsg()+"=================="+System.currentTimeMillis());
			    }
				System.out.println(2);
			}
			System.out.println(3);
		}catch(Exception e){
	    	e.printStackTrace();
	    }
		
	}

执行结果如下:

1

call执行时间=======1471532412386namehello word0=======age0

0==================1471532412386

hello word0==================1471532412386

call执行时间=======1471532412386namehello word9=======age9

call执行时间=======1471532412386namehello word1=======age1

1==================1471532412386

hello word1==================1471532412386

可以看出整个执行,123的三个输出语句之打印了一个1,说明了这个方法一执行,结果停在了for循环里面,为什么会这样?有必要好好解释一下,首先我这边定义的是一个最大线程数为2,任务阻塞列表数量为1,且超出部分的任务会销毁旧任务的线程池,然后我们看第一个for循环,循环10次,相当于建立10个线程去处理,但我只有两个线程可以用,所以第一次循环和第二次循环分别是被定义的两个线程拿去执行了,但第三次循环的时候,两个线程还没运算结束,所以第三个任务就进了阻塞列表,在之后由于没有空闲的线程,456789次循环的全部把上一次的销毁了,结果最后阻塞列表里面留下了第10次任务(所以可以看到输出了9),这边091的顺序是随机的,可以看到他们的执行时间也是一样的。

在说说为什么会停在for循环里面的,上面说到后来的任务把前面的任务都销毁了,只剩下019,事实上future要到调用get方法的时候才会去取结果,而get方法再调用时会将线程阻塞,值得取到值为止,由于第三次循环的任务被销毁了,所以get在第三次调用时就取不到值了,也就一直停在那了,这就是为什么01能正常输出,9没了(早就卡在那边了)。如果你debug一下就很清楚的可以看懂了。