0

在我的 Java Web 应用程序中,我有一个方法可以结束大约 200 封电子邮件。由于电子邮件服务器延迟,整个过程大约需要 7 分钟。这种批量电子邮件发送必须是用户操作的结果。我当然不希望用户在被转发到下一个之前必须等待那么长时间,更不用说 Apache 无论如何都会超时,所以我正在尝试实现 FutureTask 以使进程在继续时在单独的线程中运行其余代码如下:

Some code;

Runnable r = (Runnable)new sendEmails(ids);
FutureTask task = new FutureTask(r, null);
Thread t = new Thread(task);
t.start();

Some more code;

但是,该应用程序仍会等待 FutureTask 完成,然后再继续。我对这样的想法持开放态度,即这也不是在另一个线程中运行一些代码同时继续执行脚本的其余部分的最佳方式。有没有更好的方法/我如何使这个工作?

4

1 回答 1

0

看起来您在 for 循环中旋转了 200 多个线程。这会给机器带来很大的负担,并且由于每个线程分配的每个堆栈的大小,在 JVM 内存不足之前不会占用太多线程,最初会导致大量 GC 和 JVM 锁定,然后可能在足够高的负载下,崩溃。

遗憾的是,这可能会也可能不会解释为什么您的代码正在等待 FutureTasks 完成。它可能只是通过创建/调度这么多线程来等待由于抖动;但话又说回来,它可能不会。很可能还有其他东西可以同步您从上面的代码片段中删除的代码。

一种让您查找是否隐藏某处的棘手同步的方法是在运行代码时按 ctrl-break(假设您从命令行运行,intellij/eclipse 都有一个方便的堆栈转储图标)。这将导致系统中每个线程的堆栈转储出现。通过这样做,您将能够找到正在等待未来任务完成的用户线程,并且它会说出它正在等待哪个监视器。如果它不等待,那么你有一个不同的问题。例如,系统在短时间内创建了如此多的线程,以至于它似乎在短时间内锁定或一些这样的。

但首先我会避免过多的线程创建部分,因为这可能会掩盖问题。我建议使用类似于以下的代码:

ExecutorService scheduler = Executors.newCachedThreadPool() 
scheduler.submit( task )
于 2013-03-01T19:19:45.567 回答