У меня есть метод с HandlerThread. Значение изменяется внутри Thread, и я хотел бы вернуть его в test() метод. Есть ли способ сделать это?
publicvoidtest() { ThreaduiThread=newHandlerThread("UIHandler"){ publicsynchronizedvoidrun(){ int value; value = 2; //To be returned to test() } }; uiThread.start(); }
tl;dr поток не может вернуть значение (по крайней мере, без механизма обратного вызова). Вы должны ссылаться на поток, как на обычный класс, и запрашивать значение.
Ответ 2
Вы можете использовать локальную конечную переменную array . Переменная должна быть непримитивного типа, поэтому вы можете использовать array. Вам также необходимо синхронизировать два потока, например, используя CountDownLatch:
publicvoidtest() { finalCountDownLatchlatch=newCountDownLatch(1); finalint[] value = newint[1]; ThreaduiThread=newHandlerThread("UIHandler"){ @Override publicvoidrun(){ 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. }
Вы также можете использовать Executor и a Callable подобным образом:
publicvoidtest()throws InterruptedException, ExecutionException { ExecutorServiceexecutor= Executors.newSingleThreadExecutor(); Callable<Integer> callable = newCallable<Integer>() { @Override public Integer call() { return2; } }; Future<Integer> future = executor.submit(callable); // future.get() returns 2 or raises an exception if the thread dies, so safer executor.shutdown(); }
Ответ 3
Вероятно, вы ищете Callable<V> интерфейс вместо Runnable и извлекаете значение с помощью Future<V> объекта, который также позволяет вам дождаться, пока значение будет вычислено. Вы можете достичь этого с помощью ExecutorService, который вы можете получить из Executors.newSingleThreadExecutor() .
publicvoidtest() { int x; ExecutorServicees= Executors.newSingleThreadExecutor(); Future<Integer> result = es.submit(newCallable<Integer>() { public Integer call()throws Exception { // the other thread return2; } }); try { x = result.get(); } catch (Exception e) { // failed } es.shutdown(); }
Ответ 4
Как насчет этого решения?
Он не использует класс Thread , но он параллельный и в некотором смысле выполняет именно то, что вы запрашиваете
ExecutorServicepool= Executors.newFixedThreadPool(2); // creates a pool of threads for the Future to draw from
Future<Integer> value = pool.submit(newCallable<Integer>() { @Override public Integer call() {return2;} });
Теперь все, что вы делаете, это говорите, value.get() всякий раз, когда вам нужно получить возвращаемое значение, поток запускается в ту же секунду, как вы вводите value значение, так что вам никогда не придется говорить threadName.start() об этом.
Что такое Future, это обещание программе, вы обещаете программе, что когда-нибудь в ближайшем будущем вы получите необходимое ей значение
Если вы вызовете .get() его до того, как это будет сделано, вызывающий его поток просто подождет, пока это не будет сделано