方法一、继承Thread类,重写run 方法
![preview](https://i-blog.csdnimg.cn/blog_migrate/4a7d7c19c7c8a0dfdafe9f1a6f216cb2.png)
实现分析:
任何一个线程在调用了start方法 后,都随时有可能上cup,上cpu后,直接执行run方法。这里的方案1,通过重写run方法,在run方法内加入业务需求,从而达到多线程执行的一个效果。
方式二、实现Runnable 接口、并将runnable对象赋值给Thread对象
![preview](https://i-blog.csdnimg.cn/blog_migrate/bb1b9146cd29f5add5346345a18cab13.png)
实现分析:
给Thread 的runnable 赋值,在线程执行run方法的时候,实际执行的是Runnable对象的run方法。
方式对比:方式二更加面向对象
方式2,单独的Runnable对象,对应相对独立的业务内容,而Thread 线程对象则只是一个业务执行的容器。这样面向对象是更加合理的。而方式1,通过继承Thread ,覆盖run方法。这样最终将原本没有关系的两个类,揉到一体。这样耦合更高。
参考:https://zhuanlan.zhihu.com/p/56518031
方式三、实现Callable 接口,
将Callable对象赋值线程池对象ExecutorService或者将将Callable对象封装到FutureTask,并将其传给Thread 执行
package yxxy.c_026;
import java.util.concurrent.*;
public class T06_Future {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Call1 call1 = new T06_Future().new Call1();
Call2 call2 = new T06_Future().new Call2();
FutureTask<Integer> task=new FutureTask<>(call1);
new Thread(task).start();
System.out.println(task.get());//阻塞
ExecutorService service= Executors.newFixedThreadPool(5);
Future<Integer> f=service.submit(call2);
System.out.println(f.get());
System.out.println(f.isDone());
}
class Call1 implements Callable<Integer>
{
@Override
public Integer call() throws Exception {
TimeUnit.MILLISECONDS.sleep(500);
return 1000;
}
}
class Call2 implements Callable<Integer>
{
@Override
public Integer call() throws Exception {
TimeUnit.MILLISECONDS.sleep(500);
return 1;
}
}
}