Java 从线程返回值
我有一个带有Java 从线程返回值,java,android,multithreading,Java,Android,Multithreading,我有一个带有HandlerThread的方法。在线程中更改了一个值,我想将其返回到test()方法。有办法做到这一点吗 public void test() { Thread uiThread = new HandlerThread("UIHandler"){ public synchronized void run(){ int value; value = 2; //To be returned to test(
HandlerThread
的方法。在线程中更改了一个值,我想将其返回到test()
方法。有办法做到这一点吗
public void test()
{
Thread uiThread = new HandlerThread("UIHandler"){
public synchronized void run(){
int value;
value = 2; //To be returned to test()
}
};
uiThread.start();
}
通常你会这样做
public class Foo implements Runnable {
private volatile int value;
@Override
public void run() {
value = 2;
}
public int getValue() {
return value;
}
}
然后,您可以创建线程并检索该值(假定该值已设置)
tl;dr
线程无法返回值(至少在没有回调机制的情况下是如此)。您应该像普通类一样引用线程并请求值 您要查找的可能是可调用的
接口,它代替了可运行的
,并使用未来的
对象检索值,该对象还允许您等待值计算完成。您可以通过执行器服务实现这一点,该服务可以从执行器.newSingleThreadExecutor()
获得
公共无效测试(){
int x;
ExecutorService es=Executors.newSingleThreadExecutor();
未来结果=es.submit(新的可调用(){
公共整数调用()引发异常{
//另一根线
返回2;
}
});
试一试{
x=result.get();
}捕获(例外e){
//失败
}
es.shutdown();
}
您可以使用局部最终变量数组。变量必须是非基元类型,因此可以使用数组。您还需要同步这两个线程,例如使用:
您还可以使用和,如下所示:
public void test() throws InterruptedException, ExecutionException
{
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() {
return 2;
}
};
Future<Integer> future = executor.submit(callable);
// future.get() returns 2 or raises an exception if the thread dies, so safer
executor.shutdown();
}
public void test()抛出InterruptedException、ExecutionException
{
ExecutorService executor=Executors.newSingleThreadExecutor();
Callable Callable=new Callable(){
@凌驾
公共整数调用(){
返回2;
}
};
未来=执行人提交(可调用);
//future.get()返回2,或者在线程死亡时引发异常,因此更安全
executor.shutdown();
}
如果希望从调用方法获得值,那么它应该等待线程完成,这使得使用线程有点毫无意义
为了直接回答您的问题,该值可以存储在调用方法和线程都有引用的任何可变对象中。您可以使用外部的this
,但是除了一些简单的例子之外,它不会特别有用
关于问题中代码的一点注意事项:扩展
线程通常是糟糕的风格。事实上,不必要地扩展类是一个坏主意。我注意到由于某种原因,您的run
方法是同步的。现在,由于本例中的对象是线程
,您可能会干扰线程
使用其锁的任何内容(在参考实现中,与连接
,IIRC有关)。此解决方案如何
它不使用Thread类,但它是并发的,并且在某种程度上它完全按照您的请求执行
ExecutorService pool = Executors.newFixedThreadPool(2); // creates a pool of threads for the Future to draw from
Future<Integer> value = pool.submit(new Callable<Integer>() {
@Override
public Integer call() {return 2;}
});
ExecutorService池=Executors.newFixedThreadPool(2);//创建一个线程池,供将来使用
Future value=pool.submit(new Callable()){
@凌驾
公共整数调用(){return 2;}
});
现在,只要说value.get()
,每当需要获取返回的值时,线程就会在你给value
一个值的那一刻启动,这样你就不必说threadName.start()
未来是什么
是对程序的承诺,你向程序承诺你会在不久的将来得到它所需要的价值
如果在完成之前对其调用.get()
,调用它的线程只需等待,直到它完成为止使用上述答案中描述的Future来执行该任务,但与f.get()相比,它会阻塞线程直到得到结果,这违反了并发性
最好的解决办法是使用番石榴的上市产品。例如:
ListenableFuture<Void> future = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1, new NamedThreadFactory).submit(new Callable<Void>()
{
@Override
public Void call() throws Exception
{
someBackgroundTask();
}
});
Futures.addCallback(future, new FutureCallback<Long>()
{
@Override
public void onSuccess(Long result)
{
doSomething();
}
@Override
public void onFailure(Throwable t)
{
}
};
ListenableFuture=MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1,newnamedthreadfactory)。submit(new Callable())
{
@凌驾
public Void call()引发异常
{
someBackgroundTask();
}
});
Futures.addCallback(future,newfuturecallback()
{
@凌驾
成功时公开作废(长期结果)
{
doSomething();
}
@凌驾
失效时的公共无效(可丢弃的t)
{
}
};
只需对代码稍加修改,就可以以更通用的方式实现
final Handler responseHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Result from UIHandlerThread:"+(int)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
HandlerThread handlerThread = new HandlerThread("UIHandlerThread"){
public void run(){
Integer a = 2;
Message msg = new Message();
msg.obj = a;
responseHandler.sendMessage(msg);
System.out.println(a);
}
};
handlerThread.start();
解决方案:
在UI线程中创建一个处理程序
,称为responseHandler
从UI线程的活套
初始化此处理程序
在HandlerThread
中,在此responseHandler上发布消息
handleMessgae
显示一个带有从消息接收的值的Toast
。此消息对象是通用的,您可以发送不同类型的属性
使用这种方法,您可以在不同的时间点向UI线程发送多个值这个HandlerThread
上有许多Runnable
对象,每个Runnable
都可以在Message
对象中设置值,UI线程可以接收这些值。从Java 8开始,我们就有了CompletableFuture
。
在您的情况下,您可以使用方法supplyAsync
在执行后获得结果
请找一些参考资料
CompletableFuture CompletableFuture
=CompletableFuture.SupplySync(()->yourMethod());
completableFuture.get()//为您提供值
这里有一个更简洁的方法,您只需要对现有代码进行一些更改。目标是从线程中获取结果。它实际上不必是返回结果。相反,使用回调样式获取该结果并执行进一步的处理
ExecutorService pool = Executors.newFixedThreadPool(2); // creates a pool of threads for the Future to draw from
Future<Integer> value = pool.submit(new Callable<Integer>() {
@Override
public Integer call() {return 2;}
});
ListenableFuture<Void> future = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1, new NamedThreadFactory).submit(new Callable<Void>()
{
@Override
public Void call() throws Exception
{
someBackgroundTask();
}
});
Futures.addCallback(future, new FutureCallback<Long>()
{
@Override
public void onSuccess(Long result)
{
doSomething();
}
@Override
public void onFailure(Throwable t)
{
}
};
final Handler responseHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Result from UIHandlerThread:"+(int)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
HandlerThread handlerThread = new HandlerThread("UIHandlerThread"){
public void run(){
Integer a = 2;
Message msg = new Message();
msg.obj = a;
responseHandler.sendMessage(msg);
System.out.println(a);
}
};
handlerThread.start();
CompletableFuture<Integer> completableFuture
= CompletableFuture.supplyAsync(() -> yourMethod());
completableFuture.get() //gives you the value
public class Test {
public static void main(String[] args) {
String str = args[0];
int count = 0;
Thread t = new Thread(() ->
someFuncToRun(str, count, (value) -> {
System.out.println(value);
return value;
}));
t.start();
}
// Here I even run a recursive method because run things in the
// a thread sometime is to delegate those heavy lifting elsewhere
public static String someFuncToRun(String str, int ctn, Callback<String> p) {
++ctn;
if (ctn == 10) {
System.out.println("End here");
return p.cb(str);
}
System.out.println(ctn + " times");
return someFuncToRun(str + " +1", ctn, p);
}
}
// The key is here, this allow you to pass a lambda callback to your method
// update: use generic to allow passing different type of data
// you could event make it <T,S> so input one type return another type
interface Callback<T> {
public T cb(T a);
}
public static void main(String[] args) throws InterruptedException {
AtomicInteger value = new AtomicInteger(0);
Thread thread = new Thread(() -> value.set(2));
thread.start();
thread.join();
System.out.println(value.get());
}