笔记大纲
- 获取多线程方式(4种)
- Runnable&Callable接口区别
- 如何使用Callable接口
- FutureTask是什么?(测试代码+结果)
一、获取多线程方式(4种)
传统的是继承thread
类和实现runnable
接口;java5后又实现callable
接口和在java线程池
(常驻堆中的养老区)获得。
二、Runnable&Callable接口区别
class MyTread1 implements Runnable{
@Override
public void run() {
}
}
//Callable接口有返回值
class MyThread2 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
return null;
}
}
public class CallableDemo {
}
区别 | runnable接口 | Callable接口 |
---|---|---|
是否有返回值 | 否 | 有 |
是否抛异常 | 否 | 有 |
落地方法不一样 | run()方法 | call方法 |
三、如何使用Callable接口
1.查看API,Thread类构造方法无Callable
public class CallableDemo {
public static void main(String[] args) {
new Thread(new MyThread1(),"AA").start();//构造方法--Runnable对象
new Thread(new MyThread2(),"BB").start(); //实现Callable接口的类无法作为构造参数【报错】
}
}
2.利用java多态,一个类可以实现多个接口,找“中间人(Runnable-FutureTask)”
public class CallableDemo {
public static void main(String[] args) {
new Thread(new MyThread1(),"AA").start();//构造方法--Runnable对象
//new Thread(new MyThread2(),"BB").start(); //实现Callable接口的类无法作为构造参数【报错】
FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread2());
new Thread(ft, "BB").start();
}
}
java.lang.Runnable接口的实现类FutureTask:
java.lang.Runnable接口的实现类FutureTask(构造方法)
java.lang.Runnable接口的实现类FutureTask(get方法)
java.util.concurrent包中类FutureTask
四、FutureTask是什么?
FutureTask
表示未来任务,采用异步调用。
在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future
对象在后台完成,当主线程将来需要时,就可以通过Future
对象获得后台作业的计算结果或者执行状态。
一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果(只计算一次,get方法放到最后 )。仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get
方法。一旦计算完成,就不能再重新开始或取消计算。get
方法获取的结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常。
FutureTask单起一个线程,用于计算复杂的任务,与主线程分开,主线程可以专注于业务流程不会被阻塞,前提是在要计算完后去get结果,没有完成就会阻塞。
测试代码1-1:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//Callable接口
class MyThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()
+"======"+"hello,lindaxia");
return 200;//200表示执行成功
}
}
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread());
new Thread(ft, "ThreadName-AA").start();
System.out.println(ft.get());
}
}
打印结果:
测试代码1-2:
模拟主线程计算尚未完成,则阻塞 get 方法
//Callable接口
class MyThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
TimeUnit.SECONDS.sleep(3);//睡眠3秒
System.out.println(Thread.currentThread().getName()
+"======"+"hello,lindaxia");
return 200;//200表示执行成功
}
}
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread());
new Thread(ft, "ThreadName-AA").start();
System.out.println(ft.get());
System.out.println("=====主线程名测试======"+Thread.currentThread().getName());
}
}
打印结果:
期望结果:main线程先输出,最后才去get!现在睡眠3s,才会输出如下!
测试代码1-3:
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread());
new Thread(ft, "ThreadName-AA").start();
//修改main线程输出外置,在get()之前!!!!
System.out.println("=====主线程名测试======"+Thread.currentThread().getName());
System.out.println(ft.get());
}
}
打印结果:
达到期望结果,主线程先输出,再睡眠3s,接着打印结果!
测试代码2-1:
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> ft= new FutureTask<Integer>(() -> {
TimeUnit.SECONDS.sleep(3);//睡眠3秒
System.out.println(Thread.currentThread().getName()
+ "======" + "hello,lindaxia");
return 200;//200表示执行成功
});
//启动两个线程
new Thread(ft, "ThreadName-AA").start();
new Thread(ft, "ThreadName-BB").start();
System.out.println("=====主线程名测试======"+Thread.currentThread().getName());
//get()只输出一次,FutureTask只执行一次(ThreadName-AA/BB不确定谁执行)
System.out.println(ft.get());
System.out.println(ft.gdayiet());
}
}
打印结果:
测试代码2-2
两个实例执行两次(计算两次)!
//Callable接口
class MyThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
TimeUnit.SECONDS.sleep(3);//睡眠3秒
System.out.println(Thread.currentThread().getName()
+ "======" + "hello,lindaxia");
return 200;//200表示执行成功
}
}
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread());
new Thread(ft, "ThreadName-AA").start();
System.out.println("=====主线程名测试======"+Thread.currentThread().getName());
System.out.println(ft.get());*/
FutureTask<Integer> ft= new FutureTask<Integer>(() -> {
TimeUnit.SECONDS.sleep(3);//睡眠3秒
System.out.println(Thread.currentThread().getName()
+ "======" + "hello,lindaxia");
return 200;//200表示执行成功
});
//启动两个线程
FutureTask<Integer> ft2= new FutureTask<Integer>(new MyThread());
new Thread(ft, "ThreadName-AA").start();
new Thread(ft2, "ThreadName-BB").start();
System.out.println("=====主线程名测试======"+Thread.currentThread().getName());
//get()只输出一次,FutureTask只执行一次(ThreadName-AA/BB不确定谁执行)
System.out.println(ft.get());
System.out.println(ft2.get());
}
}
打印结果:
测试代码3-1:
FutureTask方法isDone()可判断是否计算完(完成任务),true表示计算完,false表示没计算完。
if(!ft2.isDone()){
System.out.println("=====没计算完,等待中======");//false就打印
}
☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!
☞本人博客:https://coding0110lin.blog.csdn.net/ 欢迎转载,一起技术交流吧!