线程的挂起操作suspend已经被java所摒弃,原因在于它会导致死锁,加入一个线程拥有了某个资源时被挂起,那么等待该资源释放的其他线程将会无法得到该资源,会陷入
死锁,那么和suspend配套使用的resume也被摒弃。
同时stop操作也会引起严重的系统错误,也被摒弃了,那么线程的停止问题就出现了。
想要终止某一个线程的最安全做法就是从它的run()方法中退出,那么调用interrupt()操作是成为终止线程的重要一步。
中断机制是一种协作机制,也就是说通过终端不能直接终止另一个线程,它只是告诉该线程需要停止这样一个操作,是否终端、以及终止的时机需要该线程自己处理。
所以可以使用一个变量来控制合适从run方法中退出。
根据How to stop a Thread具体的做法是:
1.使用violate Thread变量来标识线程是否停止。
2.停止线程时,需要调用停止线程的interrupt()方法,因为线程有可能在wait()或sleep(), 提高停止线程的即时性。
3.对于blocking IO的处理,尽量使用InterruptibleChannel来代替blocking IO。
所以最好的实现为:
public class MyThreadTwo implements Runnable{
Integer number;
public volatile Thread myThread;
MyThreadTwo(int number){
this.number = number;
}
public void stopThread(){
Thread tempThread = myThread;
myThread = null;
if(tempThread != null){
tempThread.interrupt();
}
//Thread.currentThread().interrupt();//不能使用,currentThread是调用stopThread的线程
}
@Override
public void run() {
// TODO Auto-generated method stub
if(myThread == null){
return;
}
try {
Thread.sleep(10);
//todo;dosomething
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException("Stopped by ifInterruptedStop()");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
//必须是多个线程共享资源,同步才有意义
Integer m = 40;
MyThreadTwo thread = new MyThreadTwo(m);
thread.myThread = new Thread(thread);
thread.myThread.start();
Thread.sleep(100);
thread.stopThread();
}
}
更加简洁的方案是使用boolean变量替换Thread
private volatile boolean running = true;
public void stopThread(){
running = false;
}
@Override
public synchronized void run() {
// TODO Auto-generated method stub
while(running){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
Integer m = 40;
MyThreadTwo runnable = new MyThreadTwo(m);
Thread thread = new Thread(runnable);
thread.start();
Thread.sleep(100);//等100ms后停止
runnable.stopThread();
thread.join();//等待结束
}