为什么Java中不推荐使用Thread.stop()
?在他们的网站上,我看到以下内容:
为什么
Thread.stop
已被弃用?因为它本质上是不安全的。停止线程会导致它解锁已锁定的所有监视器。 (当
ThreadDeath
异常向上传播时,监视器将被解锁。)如果先前受这些监视器保护的任何对象处于不一致状态,则其他线程现在可以以不一致的状态查看这些对象。据说这些物体已被损坏。当线程对受损对象进行操作时,可能会导致任意行为。这种行为可能很微妙并且难以检测,或者可能是明显的。与其他未经检查的异常不同,ThreadDeath
会默默地杀死线程;因此,用户没有警告他的程序可能被破坏。腐败可以在实际损害发生后的任何时间显现,甚至在未来几小时或几天。
我不明白“监视器”是什么意思。无论如何,我的问题是如果不应该调用Thread.stop()
那么Java线程应该如何被停止?
答案 0 :(得分:38)
你问:
我的问题是,如果没有办法在Java中停止线程然后如何停止线程?
答案:在Java中,没有干净,快速或可靠的方法来阻止线程。
线程终止并不是那么简单。一个正在运行的线程,通常被许多作者称为轻量级进程,它有自己的堆栈,并且是它自己命运的主人(井守护进程)。它可能拥有文件和套接字。它可能会持有锁。突然终止并不总是容易的:如果线程正在写入文件并且在完成写入之前被杀死,则可能会出现不可预测的后果。或者当线头被击中时,线程所持有的监视器锁怎么办?
相反,Threads依赖于名为 Interruption 的合作机制。这意味着线程只能信号其他线程停止,而不是强制它们停止。
要在Java中停止线程,我们依赖于一个名为Interruption的合作机制。这个概念很简单。要停止一个线程,我们所能做的只是传递一个信号,即中断它,请求线程在下一个可用的机会停止。就这样。没有人知道接收器线程可能对信号做了什么:它甚至可能不会检查信号;或者更糟糕的是忽略它。
来源:http://10kloc.wordpress.com/2013/03/03/java-multithreading-steeplechase-stopping-threads/
答案 1 :(得分:8)
正确的方法是使用联接。而不是过早地停止线程的执行,join将等待线程完成执行,然后再转到下一个语句。
Thread exampleThread = new Thread(){
public void run(){
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
//handle the exception
}
}
};
exampleThread.start();
exampleThread.join();
这里,exampleThread.join()将等到exampleThread完成执行,然后再转到下一个语句。但是,确保线程完成执行的责任在于程序员。 本质上,没有办法阻止一个线程,但如果你设计正确,你就不需要停止线程了。
答案 2 :(得分:7)
当您的线程正确处理中断时,应该可以使用ExecutorService
接口立即终止它。根据Oracle文档ExecutorService.shutdownNow()
方法,尝试在不等待终止的情况下停止所有正在执行的任务。但是,除了尽力而为之外,没有任何保证可以阻止它们。以下是一些示例代码:
class MyThread implements Runnable{
@Override
public void run() {
for (int i = 1; i < 10000000; i++)
try {
System.out.println(i + " ThreadID: " + Thread.currentThread().getId());
if (Thread.interrupted())
throw new InterruptedException();
} catch (InterruptedException e) {
return;
}
}
}
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(new MyThread());
executor.submit(new MyThread());
executor.submit(new MyThread());
executor.shutdownNow();
没有终止,每个线程应该向控制台打印消息10000000次。 executor.shutdownNow()
方法立即停止所有三个线程。
答案 3 :(得分:3)
来自https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html:
stop的大多数用法应该由代码修改,该代码只是修改某个变量以指示目标线程应该停止运行。目标线程应该定期检查此变量,并且如果变量指示它将停止运行,则以有序的方式从其run方法返回。为了确保快速通信停止请求,变量必须是易失性的(或者必须同步对变量的访问) )。
答案 4 :(得分:1)
停止线程的逻辑应该在线程的实现中处理,以便确保一切都按您希望的方式进行。
例如,您可以创建一个cancel()
方法来更改线程的状态,该方法会循环检查。像这样:
class StoppableThread implements Runnable {
boolean isCancelled = false;
public void run() {
while (!isCancelled) {
System.out.println("Thread is running with all its might!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void cancel () {
isCancelled = true;
}
}