浅谈Java获得多线程的返回结果方式(3种)
一:Java创建线程方式
继承Thread类或者实现Runnable接口。
但是Runnable的run()方法是不带返回值的,那如果我们需要一个耗时任务在执行完之后给予返回值,应该怎么做呢?
第一种方法:在Runnable的实现类中设置一个变量V,在run方法中将其改变为我们期待的结果,然后通过一个getV()方法将这个变量返回。
packagecom.test.thread;
importjava.util.*;
importsun.swing.AccumulativeRunnable;
//获得线程的返回结果方式一
/*
*在runnable实现类中设置一个变量x,在run方法中将其改变为我们期待的结果,然后通过一个getX()方法将这个变量返回
*/
publicclassRunnableTest{
publicstaticvoidmain(String[]args)throwsException{
System.out.println("使用Runnable获取返回结果");
Listworkers=newArrayList<>(10);
Listtasks=newArrayList<>(10);
//创建10个线程,每个线程分别负责累加1-10,11-20,.........,91-100
for(inti=0;i<10;i++){
RunnableAcctiontask=newRunnableAcction(i*10+1,(i+1)*10);
Threadwork=newThread(task,"累加器线程"+i);
workers.add(work);
tasks.add(task);
work.start();
}
inttotal=0;
for(inti=0;i
第二种方法:使用Callable和FutureTask。
使用FutureTask的过程如下:
(1)通过一个Callable任务或者一个Runnable(一开始就指定result)任务构造FutureTask;
(2)将FutureTask交给Thread去运行;
(3)使用FutureTask的get方法(或者Thread的join方法)阻塞当前线程直到获得任务的结果。
importjava.util.*;
importjava.util.concurrent.*;
publicclassCallableTest{
publicstaticvoidmain(String[]args)throwsException{
System.out.println("使用Callable获得返回结果:");
List>futureTasks=newArrayList<>(10);
//新建10个线程,每个线程分别负责累加1~10,11~20,...,91~100
for(inti=0;i<10;i++){
AccumCallabletask=newAccumCallable(i*10+1,(i+1)*10);
FutureTaskfutureTask=newFutureTask<>(task);
futureTasks.add(futureTask);
Threadworker=newThread(futureTask,"慢速累加器线程"+i);
worker.start();
}
inttotal=0;
for(FutureTaskfutureTask:futureTasks){
total+=futureTask.get();//get()方法会阻塞直到获得结果
}
System.out.println("累加的结果:"+total);
}
staticfinalclassAccumCallableimplementsCallable{
privatefinalintbegin;
privatefinalintend;
publicAccumCallable(intbegin,intend){
this.begin=begin;
this.end=end;
}
@Override
publicIntegercall()throwsException{
intresult=0;
for(inti=begin;i<=end;i++){
result+=i;
Thread.sleep(100);
}
System.out.printf("(%s)-运行结束,结果为%d\n",
Thread.currentThread().getName(),result);
returnresult;
}
}
}
二:FutureTask介绍
FutureTask可用于异步获取执行结果或取消执行任务的场景。通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过FutureTask的get方法异步获取执行结果。因此,**FutureTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。**另外,FutureTask还可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutureTask的执行等。
一个FutureTask可以用来包装一个Callable或是一个runnable对象。因为FurtureTask实现了Runnable方法,所以一个FutureTask可以提交(submit)给一个Excutor执行(excution)。
FutureTask执行多任务计算的使用场景:
利用FutureTask和ExecutorService,可以用多线程的方式提交计算任务,主线程继续执行其他任务,当主线程需要子线程的计算结果时,再异步获取子线程的执行结果。
importjava.util.*;
importjava.util.concurrent.*;
publicclassFutureTest1{
publicstaticvoidmain(String[]args){
Tasktask=newTask();//新建异步任务,然后执行futureTask
FutureTaskfuture=newFutureTask(task){
//异步任务执行完成,回调
@Override
protectedvoiddone(){
try{
System.out.println("future.done():"+get());
}catch(InterruptedExceptione){
e.printStackTrace();
}catch(ExecutionExceptione){
e.printStackTrace();
}
}
};
//创建线程池(使用了预定义的配置)
ExecutorServiceexecutor=Executors.newCachedThreadPool();
executor.execute(future);
try{
Thread.sleep(1000);
}catch(InterruptedExceptione1){
e1.printStackTrace();
}
//可以取消异步任务
//future.cancel(true);
try{
//阻塞,等待异步任务执行完毕-获取异步任务的返回值
System.out.println("future.get():"+future.get());
}catch(InterruptedExceptione){
e.printStackTrace();
}catch(ExecutionExceptione){
e.printStackTrace();
}
}
//异步任务
staticclassTaskimplementsCallable{
//返回异步任务的执行结果
@Override
publicIntegercall()throwsException{
inti=0;
for(;i<10;i++){
try{
System.out.println("异步任务:"+Thread.currentThread().getName()+"_"+i);
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
returni;
}
}
}
参考文章:
https://blog.csdn.net/chenliguan/article/details/54345993
https://blog.csdn.net/linchunquan/article/details/22382487
https://segmentfault.com/a/1190000007767231
到此这篇关于浅谈Java获得多线程的返回结果方式的文章就介绍到这了,更多相关Java多线程的返回结果内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!