1、继承Thread类
2、实现Runnable接口
3、使用Callable和Future创建线程
Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大,call()方法可以有返回值,而且可以声明抛出异常
步骤如下:
1】创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例(从java8开始可以直接使用Lambda表达式创建Callable对象)。
2】使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值
3】使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)
4】调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
代码示例:
class MyThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("**********call() ****");
//Thread.sleep(4000);
return 1018;
}
}
public class CallableDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread());
new Thread(ft, "AA").start();
new Thread(ft, "BB").start();
System.out.println(Thread.currentThread().getName()+"***********我是上课主线程");
Integer result01 = ft.get();
System.out.println("******result01: "+result01);
}
}
PS:
1、控制台只会打印一次"**********call() ****"
因为new Thread(ft, “AA”).start();只会生效一次,若想让new Thread(ft, “BB”).start();生效,需要 在创建一个FutureTask对象
2、 ft.get();方法尽量在靠后位置调用,若调用get()方法时call()方法还没有执行完,则会阻塞主线程,直到call()方法执行完成。