一:
从Java 5开始,Java提供了Callable接口,该接口是Runnable接口的增强版,Callable接口提供了一个call()方法,可以看作是线程的执行体,但call()方法比run()方法更强大。
call()方法可以有返回值。
call()方法可以声明抛出异常。
创建并启动线程的步骤如下:
1 创建Callable接口的实现类,并实现call()方法,该call()方法将作为该线程的执行体,且该call()方法有返回值,再创建Callable的实例。从Java 8开始,可以直接使用Lamda表达式创建Callable对象。
2 使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
3 使用FutureTask对象作为Thread对象的target创建并启动新线程。
4 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
二:代码
package Thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
/**
* 第三种新建线程的方式:使用Callable和Future创建线程
*/
public class ThirdThread {
public static void main(String[] args) {
// 创建Callable对象
// 先使用Lambda表达式创建Callable<Integer>对象
// 使用FutureTask来包装Callable对象
FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() -> {
int i = 0;
for ( ; i < 100 ; i++ )
{
System.out.println(Thread.currentThread().getName()
+ " 的循环变量i的值:" + i);
}
// call()方法可以有返回值
return i;
});
for (int i = 0 ; i < 100 ; i++)
{
System.out.println(Thread.currentThread().getName()
+ " 的循环变量i的值:" + i);
if (i == 20)
{
// 实质还是以Callable对象来创建、并启动线程
new Thread(task , "有返回值的线程").start();
}
}
try
{
// 获取线程返回值
System.out.println("子线程的返回值:" + task.get());
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
三:运行
main 的循环变量i的值:98
main 的循环变量i的值:99
有返回值的线程 的循环变量i的值:23
有返回值的线程 的循环变量i的值:24
有返回值的线程 的循环变量i的值:25
......
有返回值的线程 的循环变量i的值:94
有返回值的线程 的循环变量i的值:95
有返回值的线程 的循环变量i的值:96
有返回值的线程 的循环变量i的值:97
有返回值的线程 的循环变量i的值:98
有返回值的线程 的循环变量i的值:99
子线程的返回值:100
四:代码说明
程序先使用使用Lamda表达式创建一个Callable对象,然后将该实例包装成一个FutureTask对象。主线程中当循环变量i等于20时,程序启动以FutrueTask对象为target的线程。程序最后调用FutrueTask对象的get()方法来返回call()方法的返回值——该方法将导致主线程被阻塞,直到call()方法结束并返回为止。
原文链接:https://blog.csdn.net/chengqiuming/article/details/90572779
标签:变量,创建,Callable,线程,返回值,FutureTask,call From: https://www.cnblogs.com/techgy/p/17156884.html