例如,如果我有线程A和线程B.线程A是我的主线程,其中大多数应用程序运行,但是当我需要从MySQL或其他外部源获取的值时,我创建一个新线程(线程B)。 / p>
将值从线程B返回到线程A进行进一步处理而不会导致线程A等到值可用的最佳方法是什么?
答案 0 :(得分:2)
使用队列,A会定期轮询队列,B可以将值放入队列异步
答案 1 :(得分:2)
您可以使用ScheduledThreadPoolExecutor
,它将返回Future
,您无需等待。
示例使用(来自Future上的java文档)
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,因此可以由Executor执行。例如,上述带提交的结构可以替换为:
FutureTask<String> future =
new FutureTask<String>(new Callable<String>() {
public String call() {
return searcher.search(target);
}});
executor.execute(future);
答案 2 :(得分:2)
如果您有一个需要完成的任务,您可以使用Future并让其他Thread在方便的时候轮询(非阻塞)isDone()
方法。
如果该任务经常执行或者您要执行许多任务,那么使用ConcurrentLinkedQueue可能是一个更好的主意,这也是一个支持阻塞的变体,直到结果以LinkedBlockingQueue的形式传递。再说一次:只要方便,轮询列表就可以了。
如果您不想轮询,则可以使用回调功能。例如,如果使用Swing GUI,则可以从SwingUtilities类调用数据库线程invokeLater,因此在下一个可能的时间在主Swing线程上处理请求。
这是基于EventQueue类,在某些其他场景中使用它可能更方便。
答案 3 :(得分:0)
如果您不想处理执行者,只需创建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
}
答案 4 :(得分:0)
对于线程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();
}
答案 5 :(得分:0)
将主线程组织为事件循环:
BlockingQueue<Runnable> eventQueue=
new LinkedBlockingQueue<>();
for (;;) {
Runnable nextEvent=eventQueue.take();
nextEvent.run();
}
主题B:
Result r=fetchFromDB();
eventQueue.put(new ResultHandler(r));
其中ResultHandler是一个Runnable,它知道如何处理结果。