![](/img/trans.png)
[英]How to run task in separate thread for the specific amount of time and return result?
[英]Return result of thread to a separate thread
例如,如果我有线程A和线程B。线程A是我运行大多数应用程序的主线程,但是当我需要从MySQL或其他外部源获取的值时,我将创建一个新线程(线程B)。
将值从线程B返回到线程A以进行进一步处理而又不使线程A等待值可用的最佳方法是什么?
使用队列,A将定期轮询队列,B可以将值异步放入队列
您可以使用ScheduledThreadPoolExecutor
将返回Future
而您无需等待。
用法示例(来自Java Docs on Future )
interface ArchiveSearcher { String search(String target); }
class App {
ExecutorService executor = ...
ArchiveSearcher searcher = ...
void showSearch(final String target)
throws InterruptedException {
Future<String> future
= executor.submit(new Callable<String>() {
public String call() {
return searcher.search(target);
}});
displayOtherThings(); // do other things while searching
try {
displayText(future.get()); // use future
} catch (ExecutionException ex) { cleanup(); return; }
}
}
也可以从Future任务中实现相同的功能(访问上面的链接,示例仅来自此处)
FutureTask类是Future的实现,该实现实现Runnable,因此可以由执行程序执行。 例如,上面带有Submit的构造可以替换为:
FutureTask<String> future =
new FutureTask<String>(new Callable<String>() {
public String call() {
return searcher.search(target);
}});
executor.execute(future);
如果您只需要完成一项任务,则可以使用Future并让另一个线程在方便时轮询(非阻塞) isDone()
方法。
如果该任务经常执行,或者您有许多任务要执行,那么使用ConcurrentLinkedQueue可能是一个更好的主意,它还提供了一种支持阻塞的变体,直到将结果作为LinkedBlockingQueue交付为止。 再次:只要方便就在列表上进行轮询即可解决问题。
如果您不想轮询,则可以使用回调功能。 例如,如果使用Swing GUI,则可以从SwingUtilities类使数据库线程调用invokeLater ,因此在下一次可能的时间在主Swing线程上完成请求的处理。
这基于EventQueue类,在某些其他情况下使用起来可能更方便。
如果您不想与执行者打交道,只需创建一个FutureTask并将其传递给新线程即可。
FutureTask<String> f = new FutureTask<String>(new Callable<String>() {
@Override
public String call() {
return "";
}
});
new Thread(f).start();
while (Thread.currentThread().isInterrupted()) {
if (f.isDone()) {
System.out.println(f.get());
break;
}
//do smth else
}
对于线程B,声明一个实现Runnable
的类。 例如:
public class MyClass implements Runnable
{
private String input = null;
private String output = null;
public MyClass(String input)
{
this.input = input;
}
public String getOutput()
{
return output;
}
public void run()
{
output = func(input);
}
}
在线程A(这是您的主线程)中,启动线程B,然后仅在实际需要其输出的地方等待它完成。 例如:
public String myFunc(String input) throws Exception
{
MyClass object = new MyClass(input);
Thread thread = new Thread(object);
thread.start();
// Do whatever you wanna do...
// ...
// ...
// And when you need the thread's output:
thread.join();
return object.getOutput();
}
将主线程组织为事件循环:
BlockingQueue<Runnable> eventQueue=
new LinkedBlockingQueue<>();
for (;;) {
Runnable nextEvent=eventQueue.take();
nextEvent.run();
}
线程B:
Result r=fetchFromDB();
eventQueue.put(new ResultHandler(r));
ResultHandler是一个Runnable,它知道如何处理结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.