Callable和FutureTask分析

文章目录

  • Callable和FutureTask分析
    • 解决问题
    • 优势劣势
    • 应用场景
    • 组成部分
      • FutureTask
      • 使用
    • 底层原理
    • 相似对比

Callable和FutureTask分析

解决问题

  • 问题

    ​ 创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口,这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。

    ​ 如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。

  • 解决

    而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。

优势劣势

  • 优势:减少阻塞

应用场景

多线程计算,银行跑批

组成部分

FutureTask

package top.ygy.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @Description: TODO(Callable接口)
 * @author yangguangyuan
 * @date 2019年6月24日
 * 实现多线程三种方法:Thread类,实现Runnable接口,实现Callable接口
 * 1.区别:
 *  Runnable接口没有返回值,Callable接口有返回值
 *  Runnable不会抛异常,Callable回抛出异常
 *  实现方法不同,Runnable是run方法,Callable是call方法
 * 
 */
public class CallableDemo {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		//FutureTask(Callable callable) 
		FutureTask<Integer> futureTask = new FutureTask<>(new MyThread());
		Thread thread = new Thread(futureTask,"AAA");
		thread.start();
		
		System.out.println(futureTask.get());
	}
}

class MyThread implements Callable<Integer>{

	@Override
	public Integer call() throws Exception {
		System.out.println("************* com in Callable");
		return 1024;
	}
}

class MyTHread2 implements Runnable{

	@Override
	public void run() {
		
	}
}

使用

​ get方法放在最后,不能启动线程就调用get方法,线程的执行需要时间,启动线程后执行其他任务,最后需要结果时,在调用get方法获取结果,做进一步操作,这样可以减少阻塞

​ 一个futureTask启动两次,只调一次线程,多余调用,得出同样的结果,所以不计算

package top.ygy.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

/**
 * @Description: TODO(Callable接口)
 * @author yangguangyuan
 * @date 2019年6月24日
 * 
 */
public class CallableDemo {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		//FutureTask(Callable callable) 
		FutureTask<Integer> futureTask = new FutureTask<>(new MyThread());
		new Thread(futureTask,"AAA").start();;
        new Thread(futureTask,"BBB").start();;
		
//		Integer result02 = futureTask.get();//如果get方法放在其他任务前面,影响其他任务执行,造成阻塞
		System.out.println(Thread.currentThread().getName()+"******************");
		
		TimeUnit.SECONDS.sleep(3);
		
		int result01 = 100;
		while(!futureTask.isDone()) {
			
		}
		
		Integer result02 = futureTask.get();
		System.out.println("result="+(result01+result02));
	}
}

class MyThread implements Callable<Integer>{

	@Override
	public Integer call() throws Exception {
		System.out.println(Thread.currentThread().getName()+"************* com in Callable");
		TimeUnit.SECONDS.sleep(3);
		return 1024;
	}
}

底层原理

  • 问题

    ​ 如何使用Callable?在Thread的构造方法中,有直接构造Runnable接口的构造方法,但是想用Callable,发现没有传入Callable的构造方法,所以需要找到一个可以构造Callable的构造方法

  • 解决

    • 思想:构造注入,传接口(适配器模式)
    • 已知条件
      • 有Runnable接口可以进入该方法处理具体问题
      • 有Callable接口
    • 需要结果:Callable接口可以进入该方法处理具体问题
    • 过程
      • 类可以实现多个接口,寻找一个类与Runnable接口和Callable接口都有关系的类,就可以解决问题了

    FutureTask实现了Runnable接口,构造了Callable接口

相似对比

实现多线程三种方法:Thread类,实现Runnable接口,实现Callable接口

Runnable和Callable区别:

  • Runnable接口没有返回值,Callable接口有返回值
  • Runnable不会抛异常,Callable回抛出异常
  • 实现方法不同,Runnable是run方法,Callable是call方法

参考:

Java并发编程:Callable、Future和FutureTask

你可能感兴趣的:(1_计算机,1.1_java,1.1.2_多线程)