实现Runnable接口的run方法
跟上一种方式一样,我们既可以显式声明一个实现类来实现Runnable接口,可以直接使用匿名类
显式声明实现类
private void createThread4(){
Thread thread = new Thread(new myRunnable());
thread.start();
}
class myRunnable implements Runnable{
@Override
public void run() {
System.out.println("Thread4 started");
}
}
使用匿名类
private void createThread5(){
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Thread5 started");
}
};
Thread thread = new Thread(runnable);
thread.start();
}
实现Callable接口
从代码可以看出,实现Runnable的方式也很简单,但是无法获取run方法的返回值,这在很多场景下是无法接受的.如何获取线程的返回值呢?
实现Callable接口的call方法.Callable是个泛型接口,你可以根据需要指定具体类型来表示返回值类型,在实现call方法时返回该类型,具体如下:
private void createThread6(){
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 10;
}
};
//Callable<Integer> callable = () -> 10;
FutureTask<Integer> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
try {
System.out.println("Thread4 started");
int result = futureTask.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
上面显式实现了Callable接口,当然,你也可以使用匿名类或lambda表达式来实现,大家可以作为练习.然后声明FutureTask来获取该线程的返回值.因为FutureTask也实现了Runnable接口,所以我们把它作为参数传递给Thread对象,等线程启动后后调用FutureTask的get方法来获取返回值.
注意:必须先启动线程再调用FutureTask的get方法,因为该方法会阻塞当前线程,如果先调用它,而执行它的线程未启动(没有调用该线程的start方法)那么它后面的代码将永远无法得到运行.
总结
上面三种方式本质上也是一类:实现Runnable接口! Callable可以看作Runnable的变体.在下篇文章中我们将介绍如何使用线程池来创建线程