1. 继承Thread类
定义Thread类的子类,并重写该类的run方法
class MyThread extends Thread{
@Override
public void run() {
//要运行的代码
}
}
new MyThread().start() ;
2. 实现Runnable 接口
class Mythread implements Runnable {
@Override
public void run() {
//方法
}
}
3. 通过Callable和Future创建线程
//实现Callable接口
class MyThread2 implements Callable {
@Override
public Integer call() throws Exception {
return 200;
}
}
- 不可以像下面这么创建
不可以new Thread(new MyThread2(),"BB").start();
因为Thread的构造函数中没有Callable接口的参数设置
FutureTask的构造方法有
FutureTask(Callable<> callable)
创建一个FutureTask,一旦运行就执行给定的CallableFutureTask(Runnable runnable,V result)
创建一个FutureTask,一旦运行就执行给定的Ru你那边了,并安排成功完成时get返回给定的结果
其他常用的代码:get()
获取结果isDone()
判断是否计算结束
FutureTask 具体实现方法可以有两种方式(此处用的泛型参数)
第一种是
//实现Callable接口
class MyThread2 implements Callable {
@Override
public Integer call() throws Exception {
return 200;
}
}
FutureTask<Integer> futureTask1 = new FutureTask<>(new MyThread2());
第二种是
//lam表达式
FutureTask<Integer> futureTask2 = new FutureTask<>(()->{
System.out.println(Thread.currentThread().getName()+" come in callable");
return 1024;
});
创建线程new Thread(futureTask2,"lucy").start();
获取结果System.out.println(futureTask2.get());
所谓的FutureTask是在不影响主任务的同时,开启单线程完成某个特别的任务,之后主线程续上单线程的结果即可(该单线程汇总给主线程只需要一次即可)
如果之后主线程在开启该单线程,可以直接获得结果,因为之前已经执行过一次了
具体完整代码案例
//比较两个接口
//实现Runnable接口
class MyThread1 implements Runnable {
@Override
public void run() {
}
}
//实现Callable接口
class MyThread2 implements Callable {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+" come in callable");
return 200;
}
}
public class Demo1 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//Runnable接口创建线程
new Thread(new MyThread1(),"AA").start();
//Callable接口,报错
// new Thread(new MyThread2(),"BB").start();
//FutureTask
FutureTask<Integer> futureTask1 = new FutureTask<>(new MyThread2());
//lam表达式
FutureTask<Integer> futureTask2 = new FutureTask<>(()->{
System.out.println(Thread.currentThread().getName()+" come in callable");
return 1024;
});
//创建一个线程
new Thread(futureTask2,"lucy").start();
new Thread(futureTask1,"mary").start();
// while(!futureTask2.isDone()) {
// System.out.println("wait.....");
// }
//调用FutureTask的get方法
System.out.println(futureTask2.get());
System.out.println(futureTask1.get());
System.out.println(Thread.currentThread().getName()+" come over");
}
}
代码截图
4. 总结
比较Runnable接口和Callable接口
- Callable中的call()计算结果,如果无法计算结果,会抛出异常
- Runnable中的run()使用实现接口Runnable的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用该对象的run方法
- 总的来说:run()没有返回值,不会抛出异常。而call()有返回值,会抛出异常
Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()