2010-04-06 114 views
4

我有以下的Java代码:java.util.concurrent.Future.get()没有返回

final Future future = exeService.submit(
    new Runnable() { 
     public void run() { 
      myObject.doSomething(); 
     } 
    } 
); 

future.get(); 

其中exeService

java.util.concurrent.ExecutorService 

实例的问题是,myObject.doSomething()永远不会返回,因此,future.get()永远不会返回。

但是,如果我有像这样execute调用替换调用submit

exeService.execute(
    new Runnable() { 
     public void run() { 
      myObject.doSomething(); 
     } 
    } 
); 

调用myObject.doSomething()不会返回。我不知道它是否重要,但doSomething()void方法。

为什么doSomething()在使用execute时完成,但在使用submit时没有完成?

而且,我并不需要使用Future.get();这似乎是这样做的最自然的方式。 (我也碰到与CountdownLatch同样的问题。)问题的关键是,我需要等待doSomething()继续之前完成,而且,对于复杂的原因,我不会进入这里,我需要启动它在一个单独的线程。如果有另一种方法可行,那就没问题了。

+2

你在问'doSomething'的行为,但不会告诉我们任何事情。我们不能帮你在这里... – 2010-04-06 15:15:53

+0

你的问题很混乱。第一个构造应该正常工作。困惑在于“回归”。难道你不是指“完成”或“执行”?你的困惑似乎基于这样一个事实,即future.get()实际上等待可执行完成,因此会阻塞该线程并阻止它执行'future.get()之后的代码剩余部分)'线。 – BalusC 2010-04-06 15:17:54

+0

你是如何创建'exeService'的?它是一个ThreadPoolExecutor或其他东西? – nos 2010-04-06 15:39:37

回答

15

正如Executor.execute() Javadoc

在一些 在未来的时间执行给定的命令。该命令可以执行 在一个新的线程,在池 线程,或者调用线程,在 执行人 执行的自由裁量权。

因此,方法​​立即返回,让您无法查询提交任务的状态。

在另一方面ExecutorService.submit()

提交一个Runnable任务用于执行 并返回表示 任务的Future。未来的get方法将在成功完成 时返回空值 。

Future.get()会在你的情况下成功赛区后返回只有,所以从未

这进一步Future.get() documentation指出:

如有必要,等待计算 完成,然后获取其 结果。

+0

* never *?所以你暗示'myObject.doSomething();'就像是一个无限循环?为什么其他的构造能够工作呢?请记住,'void'是一个完全有效的返回值。 – BalusC 2010-04-06 15:24:50

+0

我不*暗示*相当*结论* :-)。作者说“问题是,myObject.doSomething()永远不会返回”,所以我认为这个函数是类似无限循环(如服务器线程或某事)。 – pajton 2010-04-06 15:26:58

+2

是的。那么你如何解释当使用'execute()'而不是'submit()'时它会“返回”? – BalusC 2010-04-06 15:37:50

7

我创建了一个SSCCE

package com.stackoverflow.q2585971; 

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

public class Test { 

    public static void main(String args[]) throws Exception { 
     ExecutorService executor = Executors.newCachedThreadPool(); 
     Future<?> future = executor.submit(
      new Runnable() { 
       public void run() { 
        try { 
         Thread.sleep(1000); 
        } catch (InterruptedException e) { 
         System.out.println("Epic fail."); 
        } 
       } 
      } 
     ); 

     System.out.println("Waiting for task to finish.."); 
     future.get(); 
     System.out.println("Task finished!"); 
     executor.shutdown(); 
    } 

} 

它完美的罚款。它首先打印

Waiting for task to finish..

一秒钟后,您会看到

Task finished!

所以,你的问题就出在别处。我会在这里复制我对你的问题的评论:

你的问题很混乱。第一个构造应该正常工作。困惑在于“回归”。难道你不是指“完成”或“执行”?您的困惑似乎基于这样一个事实,即future.get()实际上等待可运行完成,因此将阻止该线程并阻止其执行future.get()行后的代码剩余部分。

0

检查doSomething中的死锁。

我将开始搜索wait调用。

如果您的wait对于某些事情,您需要通过调用notifynotifyAll来通知您从另一个线程等待的对象。

1

Java期货封锁! get(). This method blocks the current thread until a future instance completes its work, thus requiring the use of one thread more than the work that must be performed just to manage what happens when it is done