在我的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完成后再继续。我很开心这个想法,这也不是在继续使用其余脚本的同时在另一个线程中运行某些代码的最佳方法。是否有更好的方法/如何使这个工作?
答案 0 :(得分:0)
看起来你在for循环中旋转了200多个线程。这将给机器带来很大的负担,并且由于每个线程分配的每个堆栈的大小,在JVM耗尽内存之前不会占用太多线程,最初导致很多GC和JVM锁定,然后可能在足够高的负载下,崩溃。
遗憾的是,这可能会或可能不会解释为什么您的代码正在等待FutureTasks完成。它似乎只是等待通过创建/调度这么多线程来进行适当的颠簸;但话说再说它可能不会。很可能还有其他东西可以同步你的代码,这些代码已经从上面的代码片段中删除了。
一种方法可以让你找到一个隐藏在某处的诡计同步的方法是在运行代码时点击ctrl-break(假设你是从命令行运行的,intellij / eclipse都有一个堆栈转储图标,这是便利)。这将导致系统中每个线程的堆栈转储出现。通过这样做,您将能够找到等待未来任务完成的用户线程,并且它将说明它正在等待哪个监视器。如果它没有等待,那么你有一个不同的问题。例如,系统会在短时间内创建如此多的线程,以至于它会在短时间内锁定一些线程。
但首先我会避免过多的线程创建部分,因为这可能会掩盖问题。我建议使用类似以下的代码:
ExecutorService scheduler = Executors.newCachedThreadPool()
scheduler.submit( task )