在Java中但愿中止线程,可使用设置标志位的方法,以下例所示:java
class SimpleTask implements Runnable{ private boolean stop = false; public void stop(){ stop = true; } @Override public void run() { while(!stop){ } System.out.println("quit"); } } public class StopThreadTest { public static void main(String[] args) { ExecutorService executor = Executors.newSingleThreadExecutor(); SimpleTask simpleTask = new SimpleTask(); executor.execute(simpleTask); executor.shutdown(); Scanner sc = new Scanner(System.in); while(sc.hasNext()){ String word = sc.next(); if(word.equals("stop")){ System.out.println("stop the task"); simpleTask.stop(); }else if(word.equals("!")) break; } } }
然而没法成功中止线程。缘由,没有同步,就不能保证后台线程什么时候“看到”main线程堆stop的值所作的改编。虚拟机将安全
while(!stop){} //转化为 if(!stop) while(true){}
改进,使用同步方法访问stop域。注意:读(getStop)写(stop)方法都要同步。ide
class SimpleTask implements Runnable{ private boolean stop = false; public synchronized void stop(){ stop = true; } public synchronized boolean getStop(){ return stop; } @Override public void run() { while(!getStop()){ } System.out.println("quit"); } } public class StopThreadTest { public static void main(String[] args) { ExecutorService executor = Executors.newSingleThreadExecutor(); SimpleTask simpleTask = new SimpleTask(); executor.execute(simpleTask); executor.shutdown(); Scanner sc = new Scanner(System.in); while(sc.hasNext()){ String word = sc.next(); if(word.equals("stop")){ System.out.println("stop the task"); simpleTask.stop(); }else if(word.equals("!")) break; } } }
使用volatile关键字能够得到一个更简洁、性能更好的版本性能
class SimpleTask implements Runnable{ private volatile boolean stop = false; public void stop(){ stop = true; } @Override public void run() { while(!stop){ } System.out.println("quit"); } } public class StopThreadTest { public static void main(String[] args) { ExecutorService executor = Executors.newSingleThreadExecutor(); SimpleTask simpleTask = new SimpleTask(); executor.execute(simpleTask); executor.shutdown(); Scanner sc = new Scanner(System.in); while(sc.hasNext()){ String word = sc.next(); if(word.equals("stop")){ System.out.println("stop the task"); simpleTask.stop(); }else if(word.equals("!")) break; } } }
缘由:虽然volatile不执行互斥访问,但它能够保证任何一个线程(好比本例中的main线程)读取该域(stop)的时候都能看到最近刚刚被写入的值。ui
结论:线程
synchronized
)。若是没有同步,就没法保证一个线程所作的修改能够被另外一个线程获知。volatile
修饰符就是一种能够接收的同步形式。参考:code
Effective Javaget
原始连接:How can I kill a thread? without using stop();同步
public class HelloWorld { public static void main(String[] args) throws Exception { Thread thread = new Thread(new Runnable() { public void run() { try { while (!Thread.currentThread().isInterrupted()) { Thread.sleep(5000); System.out.println("Hello World!"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }); thread.start(); System.out.println("press enter to quit"); System.in.read(); thread.interrupt(); } }
使用这种方法中止线程的好处:Interrupting 可让sleep()与wait()的线程直接被抛出异常,而后被终止。而不用等待其sleep完才能终止。虚拟机
但也有很多人对这种方法提出质疑,认为这样终止线程比较危险。
总的来讲使用第1种方法比较保守、安全。