有哪些方法可以不等待代码块或方法执行?

5

在Java中,不等待代码块/方法执行完成的正确方法/实践/实现/策略(或我们称之为什么)是什么?

假设有以下方法:

private void myMethod()
{
     // Some lines of code here
     .....
     .....
     .....

     anotherMethod(); // or this could be a code block

     // Again some lines of code here
     .....
     .....
     .....
}

在这种情况下,我期望myMethod()不应该等待anotherMethod()的代码执行完毕。同时我可以保证,在anotherMethod()中执行的任何内容都不会影响到后续的代码执行。

我在这里看到了@Bozho和@org.life.java提供的两种实现方式。我有点困惑该选择哪一种并继续下去。在我做出选择之前,有什么建议吗? - Gnanam
3个回答

7
如果没有依赖关系,您可以在另一个线程中启动它。
new Thread(new Runnable(){

      public void run(){
           anotherMethod();
      }  

}).start();

@org.life.java:你的代码块中只需要做一个小修正 - 改为 new Thread(...){... - Gnanam
@org.life.java:你的实现和Bozho建议的实现有什么区别? - Gnanam
@Gnanam Bozho的建议是在将来的某个时间执行给定的命令。该命令可以在新线程、池化线程或调用线程中执行,由Executor实现自行决定。 - jmj
@org,但在这种情况下,每个执行程序都使用单个线程,而且每次都会创建一个新的执行程序。因此,据我所知,它基本上是具有更多开销和不正确清理的相同事物。 - Matthew Flaschen
虽然我在原问题中没有提到,但实际上我正在向anotherMethod()传递参数。所以在编译时,我得到了“访问了内部类myParams局部变量,需要声明为最终变量”的错误。这里的myParams对象是传递给anotherMethod()的参数。在这种情况下,我该如何解决? - Gnanam
显示剩余2条评论

7
使用
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() {
    @Override
    public void run() {
       anotherMethod();
    }
});
// this is called automatically when the object is gc-ed, 
// but you should not rely on this, hence the explicit call
executor.shutdown();

引用《Effective Java》的话:
不仅应该避免编写自己的工作队列,而且通常应该避免直接使用线程。关键抽象不再是Thread,它既作为工作单元又作为执行机制。现在工作单元和机制是分开的。关键抽象是工作单元,称为任务。有两种类型的任务:Runnable和它的近亲Callable(类似于Runnable,但它返回一个值)。执行任务的一般机制是执行器服务。如果你以任务为中心,让执行器服务代表你执行它们,你就可以在选择适当的执行策略方面获得极大的灵活性。实质上,Executor Framework对于执行所做的事情就像Collections Framework对于聚合所做的事情一样。
请注意,最好只创建一个执行器,将其存储在实例字段中并重复使用它(然后关闭它)。
如果您在JavaEE 6或Spring中运行,则可以使用@Asynchronous注释您的anotherMethod()方法,容器将为您启动一个新线程。

不要忘记在使用完ExecutorService后调用shutdown()方法。 - dogbane
1
@Bozho,newSingleThreadExecutor不是用于多次使用的吗?也就是说,您有一个SingleThreadExecutor(使用一个线程),但它可以按顺序排队并执行多个作业。我在这里看不到任何好处。此外,@SiLent是正确的,您无法正确关闭服务,因为您没有保留引用。 - Matthew Flaschen
2
代码不清晰且误导性强--线程池在此方法级别上仅使用一次是很昂贵的,不应该使用。您还忘记释放线程池。 - SiLent SoNG
1
是的。这不是一个很大的开销,但它是没有明显好处的开销。 - Matthew Flaschen
1
《Effective Java》教会了我避免直接使用线程,因此我的回答是这样的。 - Bozho
显示剩余8条评论

0
如果您想在同一线程中调用方法,则该方法本身必须提供异步(即非阻塞)实现。通常,这将涉及返回某种回调,例如Future,您可以稍后轮询/查询以获取实际结果。其中一个例子是ExecutorService.submit()调用 - 您提供的代码将运行,但在后台线程中运行,让您自由地调用其他方法。
我在前面加粗了“invoke”这个词,因为在Java中基本上唯一同时发生两件事情的方法就是使用多个线程。因此,该方法/代码块/任何内容都必须以某种方式在后台线程中执行 - 通常通过使用某种线程池或适当的方法来处理。

如果该方法没有提供异步接口,那么在另一个线程中运行它的逻辑的唯一方法是自己创建该线程,正如org.life.java所建议的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接