我想从不同的线程运行一些代码,并在一段时间后让它超时。我还希望能够定期运行一些其他代码(即刷新一些输出或其他东西)。
这基本上就是我的做法:
Thread operation = new Thread() { ... };
operation.start();
// Check if Thread is still alive every 100ms
for (int i = 0; i < timeout / 100; i++) {
somethingToDoWhileWaiting(...);
if (!operation.isAlive()) {
break; // Thread is dead so we can end early
}
Thread.sleep(100);
}
if (operation.isAlive()) {
operation.interrupt(); // timed out
}
我的问题是,是否存在线程无法启动的任何方式(没有抛出某种异常),或者当我想检查它还活着时它可能还没有开始?
如同,有机会:
我致电operation.start()
并且不会引发任何错误。
我进入循环并检查它是否还活着
不是(因为它还没有开始或者出现幕后错误)?
除此之外,是否有更好的方法来检查线程是否已经结束(或者它已经正确启动了 - 我想到循环直到它还活着,但我对此有同样的担心)?
答案 0 :(得分:4)
这是使用ExecutorService和Futures的好地方:
Runnable task = new Runnable() { ... };
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Void> future = executor.submit(task);
// Check if Thread is still alive every 100ms
for (int i = 0; i < timeout / 100; i++) {
somethingToDoWhileWaiting(...);
if (!future.isDone()) {
break; // Thread is dead so we can end early
}
Thread.sleep(100);
}
if (!future.isDone()) {
future.cancel(true);
}
关于你的核心问题:线程受操作系统调度程序的支配。线程可以永远不会启动;但是,这非常不可能,因为OS调度程序非常擅长它的工作。如果在没有线程工作的情况下花费了相当多的时间,那么您的代码更有可能存在错误。
答案 1 :(得分:2)
Executors
和Futures
是其他人指出的方式。
但要专门回答你的问题
是否有任何方式线程无法启动(没有抛出某种异常),或者在我想检查它还活着的时候它可能没有启动?
回答:线程将启动或抛出异常。周期。
查看Thread.start()
方法的文档here。
除此之外,这是start方法的代码。你可以通过它来感受它。
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
private native void start0();
希望这有帮助。
答案 2 :(得分:-2)
使用Thread.join() - 它将一直阻塞,直到Thread退出。