将线程的结果返回给单独的线程

时间:2014-01-28 07:46:02

标签: java multithreading

例如,如果我有线程A和线程B.线程A是我的主线程,其中大多数应用程序运行,但是当我需要从MySQL或其他外部源获取的值时,我创建一个新线程(线程B)。 / p>

将值从线程B返回到线程A进行进一步处理而不会导致线程A等到值可用的最佳方法是什么?

6 个答案:

答案 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,它知道如何处理结果。