前面我看過不少的博客,部分有說建立線程有多種方式,但JDK1.8源碼Thread中有這麼一段話.ide
There are two ways to create a new thread of execution.One is to declare a class to be a subclass of Thread,The other way to create a thread is to declare a class that implements the Runnable interface.
官方給出的說明是本質上只有兩種方式:1.繼承Thread類,2.實現Runnable接口。但還有不少外在的表現形式,例如lambda表達式,線程池等。this
public class NewThread { /*擴展自Thread類*/ private static class UseThread extends Thread{ @Override public void run() { super.run(); // do my work; System.out.println("I am extendec Thread"); } } /*實現Runnable接口*/ private static class UseRunnable implements Runnable{ @Override public void run() { // do my work; System.out.println("I am implements Runnable"); } } public static void main(String[] args) throws InterruptedException, ExecutionException { UseThread useThread = new UseThread(); useThread.start(); UseRunnable useRunnable = new UseRunnable(); new Thread(useRunnable).start(); }
直接上代碼:spa
public class EndThread { private static class UseThread extends Thread{ public UseThread(String name) { super(name); } @Override public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName+" interrrupt flag ="+isInterrupted()); while(!isInterrupted()){ //while(!Thread.interrupted()){ System.out.println(threadName+" is running"); System.out.println(threadName+"inner interrrupt flag =" +isInterrupted()); } System.out.println(threadName+" interrrupt flag ="+isInterrupted()); } } public static void main(String[] args) throws InterruptedException { Thread endThread = new UseThread("endThread"); endThread.start(); Thread.sleep(20); endThread.interrupt();//中斷線程,其實設置線程的標識位true } }
stop()、suspend()也能中止線程,那麼爲何要將其標註爲Deprecated(過期)的方法呢?緣由就是這種方式是搶佔式的,好比:有一個任務在寫文件,文件的總大小爲10M,如今寫了5M,忽然收到stop()的中斷,致使線程忽然中止,那麼這樣就破壞了文件的完整性。使用interrupt()方法的好處就是,調用該方法時會給線程的中斷標誌位設置爲true,並把中斷線程的決定權交給線程本身,這種方式就是協做式,等任務處理完再結束。
相同點:調用interrupt()方法時,二者都能獲取線程的中斷標誌位狀態爲true 不一樣點:Thread.interrupt()在判斷完以後會將中斷標誌位重置爲false
public class EndRunnable { private static class UseRunnable implements Runnable{ @Override public void run() { while(!Thread.currentThread().isInterrupted()) { System.out.println(Thread.currentThread().getName() + " I am implements Runnable."); } System.out.println(Thread.currentThread().getName() +" interrupt flag is "+Thread.currentThread().isInterrupted()); } } public static void main(String[] args) throws InterruptedException { UseRunnable useRunnable = new UseRunnable(); Thread endThread = new Thread(useRunnable,"endThread"); endThread.start(); Thread.sleep(20); endThread.interrupt(); } }
當線程的執行體中出現了sleep、await、join等會拋出interruptException異常的方法時,須要特別注意,就例以下面的程序。線程調用interrupt方法時,線程的執行體會捕獲到interruptException異常,進入到catch中,這時會將線程的中斷標誌位重置爲false。這樣作的意義在於:若是不重置爲false的話,線程收到中斷請求立馬就結束了那麼與stop方法沒有區別了,若是重置爲false,程序能夠在catch中作未完成的工做,如釋放資源等,作完這些收尾的工做以後再手動的調用一次interrupt()方法,結束線程。線程
/** *類說明:阻塞方法中拋出InterruptedException異常後,若是須要繼續中斷,須要手動再中斷一次 */ public class HasInterrputException { private static class UseThread extends Thread{ public UseThread(String name) { super(name); } @Override public void run() { while(!isInterrupted()) { try { Thread.sleep(100); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() +" in InterruptedException interrupt flag is " +isInterrupted()); //資源釋放 //interrupt(); e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " I am extends Thread."); } System.out.println(Thread.currentThread().getName() +" interrupt flag is "+isInterrupted()); } } public static void main(String[] args) throws InterruptedException { Thread endThread = new UseThread("HasInterrputEx"); endThread.start(); Thread.sleep(500); endThread.interrupt(); } }
設置標誌標誌位,經過判斷標誌位來中斷線程,這種方式的不合理因素在於,若是線程執行體中的方法長時間被阻塞,致使循環阻塞,中斷標誌位失效。code
/** *類說明:設置標誌位中斷線程 */ public class HasInterrputException { private static class UseThread extends Thread{ private volatile boolean flag = false; public UseThread(String name) { super(name); } public void setFlag(boolean flag) { this.flag = flag; } @Override public void run() { while(!flag) { try { Thread.sleep(100); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() +" in InterruptedException interrupt flag is " +isInterrupted()); //資源釋放 //interrupt(); e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " I am extends Thread."); } System.out.println(Thread.currentThread().getName() +" interrupt flag is "+isInterrupted()); } } public static void main(String[] args) throws InterruptedException { Thread endThread = new UseThread("HasInterrputEx"); endThread.start(); Thread.sleep(500); ((UseThread) endThread).setFlag(true); } }
jdk源碼對Thread類定義了6個狀態,分別爲:blog
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }