从线程返回值

我有一个HandlerThread方法。 Thread值被改变了,我想把它返回给test()方法。 有没有办法做到这一点?

 public void test() { Thread uiThread = new HandlerThread("UIHandler"){ public synchronized void run(){ int value; value = 2; //To be returned to test() } }; uiThread.start(); } 

您可以使用本地最终variables数组。 variables需要是非原始types的,所以你可以使用一个数组。 您还需要同步这两个线程,例如使用CountDownLatch :

 public void test() { final CountDownLatch latch = new CountDownLatch(1); final int[] value = new int[1]; Thread uiThread = new HandlerThread("UIHandler"){ @Override public void run(){ value[0] = 2; latch.countDown(); // Release await() in the test thread. } }; uiThread.start(); latch.await(); // Wait for countDown() in the UI thread. Or could uiThread.join(); // value[0] holds 2 at this point. } 

你也可以像这样使用ExecutorCallable

 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 class Foo implements Runnable { private volatile int value; @Override public void run() { value = 2; } public int getValue() { return value; } } 

然后你可以创build线程并检索值(假设已经设置了该值)

 Foo foo = new Foo(); new Thread(foo).start(); // ... join through some method int value = foo.getValue(); 

tl;dr一个线程不能返回一个值(至less不是没有callback机制)。 你应该像一个普通的类一样引用一个线程,并要求价值。

您正在寻找的可能是Callable<V>接口来代替Runnable ,并使用Future<V>对象检索值,这也可以让您等待,直到计算出值。 你可以通过一个ExecutorService实现这一点,你可以从Executors.newSingleThreadExecutor()获得这个Executors.newSingleThreadExecutor()

 public void test() { int x; ExecutorService es = Executors.newSingleThreadExecutor(); Future<Integer> result = es.submit(new Callable<Integer>() { public Integer call() throws Exception { // the other thread return 2; } }); try { x = result.get(); } catch (Exception e) { // failed } es.shutdown(); } 

这个解决scheme如何?

它不使用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;} }); 

现在你只需要说value.get()当你需要获取返回的值的时候,线程就会在第二个value一个值,所以你永远不必对它说threadName.start()

Future是什么,是该计划的承诺 ,你承诺该计划,你会在不久的将来获得它需要的价值

如果在完成之前调用.get() ,那么调用它的线程将只是等待完成

如果你想从调用方法的值,那么它应该等待线程完成,这使得使用线程有点没有意义。

要直接回答你的问题,该值可以存储在任何可调对象中,调用方法和线程都有一个引用。 你可以使用外部的this ,但这不会是特别有用的,除了一些简单的例子。

关于代码的一点注意:扩展Thread通常是不好的风格。 事实上,不必要地扩展课程是一个坏主意。 我注意到你run方法是由于某种原因同步的。 现在,因为在这种情况下的对象是Thread你可能会干扰任何Thread使用它的锁(在参考实现, join ,IIRC)。

在上面的回答中描述的使用Future可以完成这个工作,但是与f.get()相比稍微不显着,会阻塞线程,直到获得违反并发的结果。

最好的解决scheme是使用Guava的ListenableFuture。 一个例子 :

  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(); 

解答:

  1. 在UI线程中创build一个名为responseHandler
  2. 从UI线程的Looper初始化这个Handler
  3. HandlerThread ,在这个responseHandler上发布消息
  4. handleMessgae显示从消息收到的值Toast 。 此消息对象是通用的,您可以发送不同types的属性。

使用这种方法,您可以在不同的时间点将多个值发送到UI线程。 你可以在这个HandlerThread上运行(post)许多Runnable对象,每个Runnable可以在Message对象中设置值,这个值可以被UI Thread接收。