java 线程中途返回一个值_JAVA多线程解惑之多线程返回值

本文介绍了如何在Java中使用Callable接口和FutureTask来获取多线程的返回值。通过示例代码展示了两种方式,一种是直接创建Thread并启动,另一种是利用ExecutorService提交任务。Future接口的使用使得在不阻塞主线程的情况下检查线程是否完成,并获取结果。
摘要由CSDN通过智能技术生成

如果有人问题你,多线程可以有返回值吗?你怎么回答?

看下面例子,我定义了一个类实现了Callable 接口

Java代码  eafe942e792fcba63b119909594e7653.png

publicclassMyCallableimplementsCallable {

@Override

publicObject call()throwsException {

inti=10;

Thread.sleep(10000);

returni;

}

}

Callable如果要想得到返回值需要通过一个叫FutureTask的类帮助。简单的做法是这样的

Java代码  eafe942e792fcba63b119909594e7653.png

publicvoidtest1() {

try{

FutureTask task = newFutureTask(newMyCallable());

newThread(task).start();

System.out.println("task return : "+ task.get().toString());

//get方法会一直阻塞,直到这个线程也就是call方法执行完毕

//可以通过调用isDone()来异步的询问是否已经完成。

} catch(InterruptedException e) {

e.printStackTrace();

} catch(ExecutionException e) {

e.printStackTrace();

}

}

还有另外一种方式可以使用

Java代码  eafe942e792fcba63b119909594e7653.png

publicvoidtest2(){

ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();

Future future = newCachedThreadPool.submit(newMyCallable());

try{

//同样可以通过future.isDone()来异步的知道线程是否已经处理完毕

System.out.println(future.get().toString());

}catch(Exception e) {

e.printStackTrace();

} finally{

newCachedThreadPool.shutdown();

}

}

通过上面的例子,我们知道了可以通过callable得到一个线程的返回值了,那么使用callable算多线程吗?

其实第一个例子的一行代码已经暴露出他有多线程的特性了

Java代码  eafe942e792fcba63b119909594e7653.png

newThread(task).start();

看看这个task是什么的东西

Java代码  eafe942e792fcba63b119909594e7653.png

publicclassFutureTaskimplementsRunnableFuture

//是RunnableFuture的一个实现

publicinterfaceRunnableFutureextendsRunnable, Future

//是Runnable 的子接口,这就是为什么可以放入Thread类中

// 同时他又有future的特性,得到返回值

为了彻底看清Future到底有什么,下面接口就是Future的完整定义了

Java代码  eafe942e792fcba63b119909594e7653.png

publicinterfaceFuture

{

publicabstractbooleancancel(booleanflag);

publicabstractbooleanisCancelled();

publicabstractbooleanisDone();

publicabstractObject get()

throwsInterruptedException, ExecutionException;

publicabstractObject get(longl, TimeUnit timeunit)

throwsInterruptedException, ExecutionException, TimeoutException;

}

现在知道了Callable是借助Runnable来实现多线程的功能,所以说它是多线程也说的过去。那么它是如何获得返回值的呢?

我们都知道线程的启动方法是start方法,然后线程内部调用了run()方法

Java代码  eafe942e792fcba63b119909594e7653.png

publicvoidrun()

{

sync.innerRun();

}

protectedvoidset(Object obj)

{

sync.innerSet(obj);

}

publicObject get()

throwsInterruptedException, ExecutionException

{

returnsync.innerGet();

}

我们的调用都深入到了sync的方面里面去了。接下来

Java代码  eafe942e792fcba63b119909594e7653.png

voidinnerRun()

{

if(!compareAndSetState(0,1))

return;

runner = Thread.currentThread();

if(getState() ==1)

{

Object obj;

try

{

obj = callable.call(); //这时候调用我们覆写的call方法了

}

catch(Throwable throwable)

{

setException(throwable);

return;

}

set(obj);//执行完之后将结果放入存起来

} else

{

releaseShared(0);

}

}

如何存,很简单,存入事先准备好的属性中

Java代码  eafe942e792fcba63b119909594e7653.png

voidinnerSet(Object obj)

{

inti;

do

{

i = getState();

if(i ==2)

return;

if(i ==4)

{

releaseShared(0);

return;

}

} while(!compareAndSetState(i,2));

result = obj;//这么存的

releaseShared(0);

done();

}

如何取

Java代码  eafe942e792fcba63b119909594e7653.png

Object innerGet()

throwsInterruptedException, ExecutionException

{

acquireSharedInterruptibly(0);

if(getState() ==4)

thrownewCancellationException();

if(exception !=null)

thrownewExecutionException(exception);

else

returnresult;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值