安全启动没有加入的线程吗?

时间:2015-08-02 21:34:26

标签: java multithreading asynchronous

在Web应用程序中我有一个方法,如果客户数量小于10,则等待另一个线程生成报告,但如果大于10,我会启动我的线程但不应用join方法,当线程完成时我通过电子邮件通知。

我对有大量执行的孤立线程以及对服务器的影响有点害怕。

好的发射是一个重的"在后台进程(异步)而不使用join方法或有更好的方法来实现它?

try {
        thread.start();
        if(flagSendEmail > 10){                     
            return "{\"message\":\"success\", \"text\":\"you will be notified by email\"}";
        }else{
              thread.join();            //the customer waits until finish           
        }
    } catch (InterruptedException e) {
             LogError.saveErrorApp(e.getMessage(), e);
             return "{\"message\":\"danger\", \"text\":\"can't generate the reports\"}";
    }

3 个答案:

答案 0 :(得分:2)

Orphan线程不是问题,只需确保run()方法有一个发送电子邮件的finally块。

问题是你无法控制线程数,这与调用join()无关。 (除非你总是等待调用者中的每一个线程,否则一开始就没有必要启动后台线程。)

解决方案是使用ExecutorService,它为您提供线程池,从而精确控制一次运行这些后台线程的数量。如果您提交的任务数超过执行程序在给定时间可以处理的任务数,则其余任务将排队等待运行。这样您就可以控制服务器上的负载。

额外的好处是,因为执行程序服务通常会回收相同的工作线程,所以提交新任务的开销较小,这意味着您无需担心自己是否拥有超过10个项目或不,一切都可以以同样的方式运行。

在您的情况下,您甚至可以考虑使用两个单独的执行程序:一个用于运行报告生成,另一个用于发送电子邮件。这样做的原因是您可能希望限制在繁忙时段发送的电子邮件数量,但不会减慢报告生成速度。

答案 1 :(得分:2)

如果您接下来做的事情是join(),那么启动一个主题是没有意义的。

我不确定我理解你要做什么,但是如果你的例子是在正确的道路上,那么这将更好,因为它避免了在{{中创建和销毁新线程(昂贵) 1}}案例:

flagSendEmail <= 10

但是很有可能,你根本不应该明确地创建新的线程。每当程序不断地创建并销毁线程时,这就表明它应该使用线程池。 (参见Runnable r = ...; if (flagSendEmail > 10) { Thread thread = new Thread(r); thread.start(); return "..."; } else { r.run(); return ??? } )的javadoc

顺便说一句:java.util.concurrent.ThreadPoolExecutor对线程t.join()没有任何作用。除了等待线程t已经死亡之外,它根本不做任何事情。

答案 2 :(得分:0)

是的,它是安全的,我不记得看到任何Thread#join()实际调用。

但这取决于你想做什么。我不知道您是否要使用生成报告或分配了一些资源的池或线程。在任何情况下,您都应该将自己限制为报告的最大线程数。如果它们被阻塞或循环(对于某些错误或差的同步),允许越来越多的线程将完全阻塞您的应用程序。

Thread#join等待引用的线程死亡。那些线程真的结束了吗?你是否在等待一个线程只是为了启动另一个线程?通常在同步对象上使用wait()notify()进行同步。

启动一个进程(Runtime#exec())可能会让事情变得更糟,除非它有助于解决一些奇怪的限制。

有一些像JConsole这样的工具可以让你对线程被锁定和其他问题有所了解。

相关问题