Java创建多线程返回结果方式

文章资讯 2020-06-17 22:32:30

Java创建多线程返回结果方式

一:Java创建线程方式
继承Thad类或者实现Runnable接口。
但是Runnable的run()方法是不带返回值的,那如果我们需要一个耗时任务在执行完之后给予返回值,应该怎么做呢?
第一种方法:在Runnable的实现类中设置一个变量V,在run方法中将其改变为我们期待的结果,然后通过一个getV()方法将这个变量返回。
ackagecom.test.thad;imortjava.util.*;
imortsun.swing.AccumulativeRunnable;
获得线程的返回结果方式一
*
*在runnable实现类中设置一个变量x,在run方法中将其改变为我们期待的结果,然后通过一个getX()方法将这个变量返回
*
ublicclassRunnableTest{
ublicstaticvoidmain(String[]args)throwsExcetion{
System.out.rintln("使用Runnable获取返回结果");
List<Thad>workers=newArrayList<>(10);
List<RunnableAcction>tasks=newArrayList<>(10);
创建10个线程,每个线程分别负责累加1-10,11-20,.........,91-100
for(inti=0;i<10;i++){
RunnableAcctiontask=newRunnableAcction(i*10+1,(i+1)*10);
Thadwork=newThad(task,"累加器线程"+i);
workers.add(work);
tasks.add(task);
work.start();
}
inttotal=0;
for(inti=0;i<workers.size();i++){
workers.get(i).join();
total+=tasks.get(i).getResult();
}
System.out.rintln("n累加的结果:"+total);
}

staticfinalclassRunnableAcctionimlementsRunnable{

rivateinta;
ublicRunnableAcction(inta,intb){
suer();
this.a=a;
this.b=b;
}
rivateintb;
rivateintsult;
@Override
ublicvoidrun(){
sult=0;
try{
for(inti=a;i<=b;i++){
sult+=i;
Thad.slee(100);
}
}catch(Excetione){
TODO:handleexcetion
}
System.out.rintf("(%s)-运行结束,结果为%dn",Thad.curntThad().getName(),sult);
}
ublicintgetResult(){获取线程返回结果
turnsult;
}
}
}第二种方法:使用Callable和FutuTask。
使用FutuTask的过程如下:
(1)通过一个Callable任务或者一个Runnable(一开始就指定sult)任务构造FutuTask;
(2)将FutuTask交给Thad去运行;
(3)使用FutuTask的get方法(或者Thad的join方法)阻塞当前线程直到获得任务的结果。
imortjava.util.*;
imortjava.util.concurnt.*;ublicclassCallableTest{ublicstaticvoidmain(String[]args)throwsExcetion{
System.out.rintln("使用Callable获得返回结果:");List<FutuTask<Integer>>futuTasks=newArrayList<>(10);
新建10个线程,每个线程分别负责累加1~10,11~20,...,91~100
for(inti=0;i<10;i++){
AccumCallabletask=newAccumCallable(i*10+1,(i+1)*10);
FutuTask<Integer>futuTask=newFutuTask<>(task);
futuTasks.add(futuTask);
Thadworker=newThad(futuTask,"慢速累加器线程"+i);
worker.start();
}inttotal=0;
for(FutuTask<Integer>futuTask:futuTasks){
total+=futuTask.get();get()方法会阻塞直到获得结果
}
System.out.rintln("累加的结果:"+total);
}staticfinalclassAccumCallableimlementsCallable<Integer>{rivatefinalintbegin;
rivatefinalintend;ublicAccumCallable(intbegin,intend){
this.begin=begin;
this.end=end;
}@Override
ublicIntegercall()throwsExcetion{
intsult=0;
for(inti=begin;i<=end;i++){
sult+=i;
Thad.slee(100);
}
System.out.rintf("(%s)-运行结束,结果为%dn",
Thad.curntThad().getName(),sult);
turnsult;
}
}
}二:FutuTask介绍
FutuTask可用于异步获取执行结果或取消执行任务的场景。通过传入Runnable或者Callable的任务给FutuTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过FutuTask的get方法异步获取执行结果。因此,**FutuTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。**另外,FutuTask还可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutuTask的执行等。
一个FutuTask可以用来包装一个Callable或是一个runnable对象。因为FurtuTask实现了Runnable方法,所以一个FutuTask可以提交(submit)给一个Excutor执行(excution)。
FutuTask执行多任务计算的使用场景:
利用FutuTask和ExecutorService,可以用多线程的方式提交计算任务,主线程继续执行其他任务,当主线程需要子线程的计算结果时,再异步获取子线程的执行结果。
imortjava.util.*;
imortjava.util.concurnt.*;ublicclassFutuTest1{ublicstaticvoidmain(String[]args){Tasktask=newTask();新建异步任务,然后执行futuTask
FutuTask<Integer>futu=newFutuTask<Integer>(task){
异步任务执行完成,回调
@Override
rotectedvoiddone(){
try{
System.out.rintln("futu.done():"+get());
}catch(InterrutedExcetione){
e.rintStackTrace();
}catch(ExecutionExcetione){
e.rintStackTrace();
}
}
};
创建线程池(使用了预定义的配置)
ExecutorServiceexecutor=Executors.newCachedThadPool();
executor.execute(futu);try{
Thad.slee(1000);
}catch(InterrutedExcetione1){
e1.rintStackTrace();
}
可以取消异步任务
futu.cancel(true);try{
阻塞,等待异步任务执行完毕-获取异步任务的返回值
System.out.rintln("futu.get():"+futu.get());
}catch(InterrutedExcetione){
e.rintStackTrace();
}catch(ExecutionExcetione){
e.rintStackTrace();
}
}异步任务
staticclassTaskimlementsCallable<Integer>{
返回异步任务的执行结果
@Override
ublicIntegercall()throwsExcetion{
inti=0;
for(;i<10;i++){
try{
System.out.rintln("异步任务:"+Thad.curntThad().getName()+"_"+i);
Thad.slee(500);
}catch(InterrutedExcetione){
e.rintStackTrace();
}
}
turni;
}
}
}