我想用SwingWorker
尝试一些想法,因为我没有太多使用它。相反,我遇到了一个问题,我无法弄清楚出了什么问题。
这是一个简短的SSCCE来证明这个问题(我知道这里的人就像SSCCE一样):
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class SwingWorkerTest
{
public static void main (String[] args)
{
SwingUtilities.invokeLater (new Runnable ()
{
@Override
public void run ()
{
new MySwingWorker (500).execute ();
new MySwingWorker (900).execute ();
new MySwingWorker (1200).execute ();
}
});
}
}
class MySwingWorker extends SwingWorker<Void, Void>
{
private int ms;
public MySwingWorker (int ms)
{
this.ms = ms;
}
@Override
protected Void doInBackground()
{
Thread t = Thread.currentThread ();
for (int i = 0; i < 50; i++)
{
try
{
Thread.sleep (ms);
}
catch (InterruptedException e)
{
e.printStackTrace ();
}
System.out.println ("I am thread with " + ms + " sleep in iteration " + i + ": " + t.getName () + " (" + t.getId () + ")");
}
return null;
}
}
所以我的程序应该创建3个SwingWorkers,在屏幕上打印一行,然后睡眠指定的毫秒数,然后再次打印该行并再次睡眠等。我在Swing的线程中创建了SwingWorker
,因为否则他们甚至都不会开始。
所以预期的输出是:
I am thread with 500 sleep in iteration 0: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 0: SwingWorker-pool-1-thread-2 (16)
I am thread with 500 sleep in iteration 1: SwingWorker-pool-1-thread-1 (15)
I am thread with 1200 sleep in iteration 0: SwingWorker-pool-1-thread-3 (17)
I am thread with 500 sleep in iteration 2: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 1: SwingWorker-pool-1-thread-2 (16)
I am thread with 500 sleep in iteration 3: SwingWorker-pool-1-thread-1 (15)
I am thread with 1200 sleep in iteration 1: SwingWorker-pool-1-thread-3 (17)
I am thread with 500 sleep in iteration 4: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 2: SwingWorker-pool-1-thread-2 (16)
I am thread with 500 sleep in iteration 5: SwingWorker-pool-1-thread-1 (15)
I am thread with 500 sleep in iteration 6: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 3: SwingWorker-pool-1-thread-2 (16)
I am thread with 1200 sleep in iteration 2: SwingWorker-pool-1-thread-3 (17)
I am thread with 500 sleep in iteration 7: SwingWorker-pool-1-thread-1 (15)
.............
等等,共计150行(3名工人x 50次迭代)
相反,我得到的输出是:
I am thread with 500 sleep in iteration 0: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 0: SwingWorker-pool-1-thread-2 (16)
I am thread with 500 sleep in iteration 1: SwingWorker-pool-1-thread-1 (15)
就是这样。只需3行。在此之后程序退出。 try catch
块之外的任何地方都没有堆栈跟踪。
1)。 1200毫秒睡觉的工人在哪里?实际上,如果我用1000毫秒替换1200毫秒,那么这个工作者也打印1行......是的,只有一行。奇怪的...
2)。为什么工人会停下来? (我没有得到150行的东西)
我在Windows 7 64位上使用 JRE 7 Update 11运行此程序。
PS:我很确定在这个版本的JRE中修复了the bug mentioned here,因为我确实得到了2个不同的值(15和16)作为在控制台上打印的线程ID。这是我怀疑的第一件事。
答案 0 :(得分:9)
我相信你需要显示一个可视化的Swing顶级窗口,以保持Swing事件线程的活动。否则,程序将因缺少非守护程序线程而关闭。
修改强>
要证明SwingWorker线程是一个守护程序线程,只需添加一行代码来测试它:
System.out.println("I am thread with " + ms + " sleep in iteration "
+ i + ": " + t.getName() + " (" + t.getId() + ")");
// **** added
System.out.println("Daemon?: " + Thread.currentThread().isDaemon());
答案 1 :(得分:9)
如果查看SwingWorker类源代码(Java SE 7)的第771行:
thread.setDaemon(true);
您将看到SwingWorker
在守护程序线程中执行,而在Java中,如果所有非守护程序线程都已完成,JVM将被终止。
答案 2 :(得分:4)
如前所述,您可以使用UI来保持线程活跃。
或者,您可以使用SwingWorker#get
(或阻止主线程终止的任何内容)等待线程完成。通过这样做,您将获得预期的输出。这是经过修改的代码,可以满足您的需求。
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import java.util.concurrent.ExecutionException;
public class SwingWorkerTest
{
public static void main (String[] args)
{
final MySwingWorker w1 = new MySwingWorker (500),
w2 = new MySwingWorker (900),
w3 = new MySwingWorker (1200);
SwingUtilities.invokeLater (new Runnable ()
{
@Override
public void run ()
{
w1.execute ();
w2.execute ();
w3.execute ();
}
});
try{
// you can replace the code in this block
// by anything that keeps the program from
// terminating before the threads/SwingWorkers.
w1.get();
w2.get();
w3.get();
}catch(InterruptedException e){
System.err.println("InterruptedException occured");
}catch(ExecutionException e){
System.err.println("InterruptedException occured");
}
}
}
class MySwingWorker extends SwingWorker<Void, Void>
{
private int ms;
public MySwingWorker (int ms)
{
this.ms = ms;
}
@Override
protected Void doInBackground()
{
Thread t = Thread.currentThread ();
for (int i = 0; i < 50; i++)
{
try
{
Thread.sleep (ms);
}
catch (InterruptedException e)
{
e.printStackTrace ();
}
System.out.println ("I am thread with " + ms + " sleep in iteration " + i + ": " + t.getName () + " (" + t.getId () + ")");
}
return null;
}
}
答案 3 :(得分:3)
您是否尝试过创建任何用户界面?或者在main的末尾放置new Object().wait();
之类的内容,以防止主线程退出?
我不是完全确定这是这种情况,但是没有任何实际的UI显示,我很确定swing工作者只是另一个线程,并且你没有配置任何守护程序线程,所以main启动它们,主要完成,并且进程退出?