Java 终止线程不会';t使用JRE 1.6_45在WindowsXP上工作
我有一个线程,它应该与SWTGUI线程同步运行,但是如果10秒后没有完成,那么超时将终止该线程。编辑:我被要求与Java1.4保持兼容 线程:Java 终止线程不会';t使用JRE 1.6_45在WindowsXP上工作,java,multithreading,rmi,legacy,Java,Multithreading,Rmi,Legacy,我有一个线程,它应该与SWTGUI线程同步运行,但是如果10秒后没有完成,那么超时将终止该线程。编辑:我被要求与Java1.4保持兼容 线程: private boolean isFinished; (...) isFinished = false; Thread t = new Thread ("getShellsThread") { public void run() { try { logger.deb
private boolean isFinished;
(...)
isFinished = false;
Thread t = new Thread ("getShellsThread") {
public void run() {
try {
logger.debug("aquirerootcont SWT entered - " + Thread.currentThread().toString());
(...)
} finally {
isFinished = true;
logger.debug ("hasShells is Finished!");
}
}
}
超时代码:
long startTime = System.currentTimeMillis();
long timeWaited;
((Display)displays.get(i)).asyncExec (t);
while(!isFinished){
timeWaited = System.currentTimeMillis() - startTime;
logger.debug("aquireRootContainer: timeWaited: " + timeWaited);
if (timeWaited > 1000) {
logger.debug(t +" Name: " + t.getName()+" took to long and will be destroyed!");
t.interrupt ();
shell = null;
break;
}
}
此代码适用于带有JRE 1.6和1.7的Windows 7和Windows 8以及IBM JRE。然而,对于Windows XP,虽然IBM JRE工作正常,但JRE 1.6_45不会
XP 1.6_45上的日志显示线程什么也不做,10秒后会显示:
Thread[getShellsThread,10,RMI Runtime] Name: getShellsThread took to long and will be destroyed!
Windows Taskmgr表示rmiregistry.exe已被终止
为什么这段代码会杀死一个特定系统上的RMI?任何线索都很好
由于需要向后兼容,目前用于超时线程的大多数方法不幸不可用 您的代码中存在严重的概念错误
Thread t = new Thread ("getShellsThread") {
};
....
((Display)displays.get(i)).asyncExec (t);
将Runnable
作为参数。您正在传递一个线程
。如果这样做,该方法将不会在其他线程上调用线程对象的run()
方法
线程对象t
从未实际启动,因此在超时代码中调用t.interrupt()
时,不会发生任何事情。当然,您没有中断实际运行run()
方法的线程
除此之外,我怀疑使用
Display.asyncExec
来运行一个可能长时间运行的任务是一个坏主意。在阅读javadoc时,很明显asyncExec在SWT用户界面线程上运行任务以显示。在运行时,UI线程将无法处理来自用户鼠标移动、按键等的事件。用户界面将“冻结”
最后,您的超时代码实际上是一个繁忙的循环,它将消耗CPU周期,直到超时过期。这是拙劣的设计
我认为正确的解决方案是去掉
asyncExec(t)
调用,而是调用t.start()
来启动线程。然后替换用于实现超时的浪费繁忙等待代码。相反,使用类实现超时。它是在Java3中引入的,因此应该可以在您的遗留平台上使用。您的代码中有一个严重的概念错误
Thread t = new Thread ("getShellsThread") {
};
....
((Display)displays.get(i)).asyncExec (t);
将Runnable
作为参数。您正在传递一个线程
。如果这样做,该方法将不会在其他线程上调用线程对象的run()
方法
线程对象t
从未实际启动,因此在超时代码中调用t.interrupt()
时,不会发生任何事情。当然,您没有中断实际运行run()
方法的线程
除此之外,我怀疑使用
Display.asyncExec
来运行一个可能长时间运行的任务是一个坏主意。在阅读javadoc时,很明显asyncExec在SWT用户界面线程上运行任务以显示。在运行时,UI线程将无法处理来自用户鼠标移动、按键等的事件。用户界面将“冻结”
最后,您的超时代码实际上是一个繁忙的循环,它将消耗CPU周期,直到超时过期。这是拙劣的设计
我认为正确的解决方案是去掉
asyncExec(t)
调用,而是调用t.start()
来启动线程。然后替换用于实现超时的浪费繁忙等待代码。相反,使用类实现超时。它是在Java 3中引入的,因此应该可以在您的旧版平台上使用。“我现在正在剪掉头发,吃掉所有的指甲…”-信息太多了!!我们不需要知道你可疑的个人习惯。堆栈跟踪肯定会有帮助。你试过使用jstack
来查看线程中发生了什么吗?如果原始线程只是等待新线程完成,那么开始一个新线程没有多大意义……你的标题似乎与你的实际问题没有任何关系。“我现在正在拔头发,吃掉所有的指甲…”-信息太多!!我们不需要知道你可疑的个人习惯。堆栈跟踪肯定会有帮助。您是否尝试过使用jstack
查看线程中发生了什么?如果原始线程只是等待新线程完成,那么启动新线程没有多大意义……您的标题似乎与实际问题没有任何关系。因此,我是否可以将其定义为可运行并将其转换为线程以调用.interrupt()?不是您实现它的方式。从理论上讲,你可以中断SWT用户界面线程,但这是一个非常糟糕的主意。但为什么它在除了Windows之外的所有机器上都能工作呢XP@Java1.6_45我不知道。可能任务总是设法完成。。。因为一些无关的原因。事实上,您在XP上遇到问题的原因可能是CPU燃烧代码,或者是由于同步问题导致的死锁。因此,我可以将其定义为可运行,并将其转换为线程以调用.interrupt()?而不是您实现它的方式。从理论上讲,你可以中断SWT用户界面线程,但这是一个非常糟糕的主意。但为什么它在除了Windows之外的所有机器上都能工作呢XP@Java1.6_45我不知道。可能任务总是设法完成。。。因为一些无关的原因。事实上,您在XP上遇到问题的原因可能是CPU燃烧代码,或者是由于同步问题而导致的死锁。