在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種方法比較保守、安全。