Callable FutureTask

对于多个在逻辑上互不依赖的耗时任务而言,并行化执行效率要比串行化执行效率高。对于这些任务往往在其执行完毕后要取得任务的执行结果。CallableFutureTask就实现了这一机制。

Callable和Runnable区别

区别

  1. callable可以携带返回值,泛型
  2. callable可以抛出异常
  3. callable的方法名是call,runnable方法名是run

联系

  • callable本质上还是要在runnable内执行

Callable和FutureTask成对出现

runnable封装了任务的具体逻辑,要进行多线程编程,需要Thraed来执行
callable封装了任务的具体逻辑,但它不能被Thread直接执行,因为Thread的构造参数中就只有runnable,所以在callableThreadTask中还有FutureTask,那么FutureTask有什么作用?

FutureTask

FutureTask的本质就是一个runnable。

  • 是runnable的实现
  • 它的构造参数接受callable
  • 并且有泛型定义,记录任务的执行结果
  • get方法可以获取callable任务的执行结果,如果任务执行完直接返回结果,任务还没执行完,调用线程会阻塞线程直至get返回结果

基于以上的特点实现一个简单的FutureTask。

public class AyFutureTask<T> implements Runnable
{
	
	/* 任务封装 */
	Callable<T> callable;

	/* 存放任务执行结果 */
	T result;
	
	/* 记录当前任务的执行状态 */
	volatile String state  = "NEW";
	
	/* 记录阻塞的线程 */
	Thread thread;
	public AyFutureTask(Callable<T> callable){
		this.callable  = callable;
	}
	

	@Override
	public void run()
	{
		try
		{
			result = callable.call();
		} catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			state = "END";
			//唤醒阻塞线程
			LockSupport.unpark(thread);
		}
	}
	
	T get(){
		if(!state.equals("END")){		
			//线程等待,不使用wait和notify的原因是因为如果nitofy比wait执行的早,
			//那么wait将一直等待下去,而使用park/unpark则无此问题
			thread = Thread.currentThread();
			LockSupport.park(); 
		}
		return result;
	}
}

使用例子

public class FutureTaskTest
{

	public static void main(String[] args) throws InterruptedException, ExecutionException
	{
		 long now  = System.currentTimeMillis();
		 System.out.println("开始测试:"+now);
		 
		Callable<String> call1 =  new Callable<String>()
		{
			@Override
			public String call() throws Exception
			{
				//1.第一部分任务
				 Thread.sleep(3000);
				 //System.out.println("获得第一步信息");
				return "第一部分结果";
			}
		};
		 
		Callable<String> call2 = new Callable<String>()
		{

			@Override
			public String call() throws Exception
			{

				 //2.第二部分任务
				 Thread.sleep(2000);
				 //System.out.println("获得第二步信息");
				return "第二部分结果";
			}
		};
		 
		 AyFutureTask<String> task1 = new AyFutureTask<String>(call1);

		 AyFutureTask<String> task2 = new AyFutureTask<String>(call2);
		 
		 Thread t1 = new Thread(task1);
		 Thread t2 = new Thread(task2);
		 t1.start();
		 t2.start();
		 
		 //get会等待线程
		 System.out.println(task1.get());
		 System.out.println(task2.get());
		 System.out.println("结束测试:"+(System.currentTimeMillis() - now));
		 
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_41768073/article/details/84327014
今日推荐