大前提:全部線程是沒有前後順序的,若是引入同步鎖,誰先得到對象鎖,誰先執行ide
線程實現方式:測試
1.繼承Thread類,重寫run方法;this
2.實現runnable接口,實現其run方法。線程
啓動方式:對象
調用線程的start方法啓動線程,start方法爲線程準備好系統資源,而後調用run方法執行代碼邏輯。繼承
經常使用方法:接口
Object對象方法:資源
wait和notify方法:這兩個方法定義在Object類中,final方法,沒法重寫,這兩方法要求被調用時線程已得到對象的鎖,所以須要放在synchronized方法或塊中調用。當執行wait方法時,線程會釋放對象的鎖,線程會處於等待狀態;調用notify時,會隨機喚醒一個等待的線程(可是不會立馬被執行),此喚醒的線程與其餘線程競爭對象鎖。get
notifyAll方法:也須要在靜態方法或靜態代碼塊中執行,會喚醒全部等待的線程跟其餘線程進行鎖的競爭;同步
當前線程對象的方法:
join:用於將當前線程插入到正在執行的線程,當前線程得到對象鎖並執行完後(銷燬後)纔會繼續進行原來正在執行線程未完成的操做。
靜態方法:
Thread.sleep方法:會讓當前線程休眠指定毫秒時間,整個過程不會釋放對象鎖。
Thread.yield方法:經當前線程從新置於就緒狀態,整個過程不會釋放對象鎖。
三種使用場景:
1.修飾靜態方法:表示對類(Class對象)的枷鎖,在進入該靜態方法前,當前線程須要得到該類的鎖。
一個線程訪問該Class對象的任何同步靜態方法,其餘線程沒法訪問該Class對象的任何同步方法。
2.修飾普通方法:表示對類實例的加鎖,在進入普通方法前,當前線程須要得到該實例的鎖(若是是當前類的不一樣對象,則不會出現同步顯現);
都一個普通方法用synchronized進行修飾,表示對對象加鎖,當一個線程調用該方法時,其餘線程沒法訪問該方法,指導第一個線程執行完或拋出異常釋放掉對象鎖,其餘線程纔有可能訪問該同步方法。
若是一個對象有多個同步方法,當一個線程訪問某個同步方法時,其餘線程也是沒法訪問該對象的任何同步方法的。
3.修飾代碼塊:表示對指定對象枷鎖,在進入代碼塊前,當前線程須要得到該指定對象的鎖
同步測試代碼以下:
/** * 同步關鍵字的使用 * 全部線程是沒有優先級的(線程執行沒有前後順序),若是引入同步鎖,誰先得到對象鎖,誰先執行 * * @author kevin * @email ly_triangle@126.com * @date 2018年3月8日 */ public class SynchronizeDemo { /** * 同步靜態方法1 */ public synchronized static void synchronizedStaticMethod1() { try { System.out.println(Thread.currentThread().getName() + ":synchronizedStaticMethod1"); Thread.sleep(2000l); System.out.println(Thread.currentThread().getName() + ":synchronizedStaticMethod1……"); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 同步靜態方法2 */ public synchronized static void synchronizedStaticMethod2() { System.out.println(Thread.currentThread().getName() + ":synchronizedStaticMethod2"); } /** * 同步普通方法1 */ public synchronized void synchronizedMethod1() { try { System.out.println(Thread.currentThread().getName() + ":synchronizedMethod1"); Thread.sleep(2000l); System.out.println(Thread.currentThread().getName() + ":synchronizedMethod1……"); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 同步普通方法2 */ public synchronized void synchronizedMethod2() { System.out.println(Thread.currentThread().getName() + ":synchronizedMethod2"); } /** * 非同步普通方法1 */ public void method1() { try { System.out.println(Thread.currentThread().getName() + ":synchronizedMethod1"); Thread.sleep(2000l); System.out.println(Thread.currentThread().getName() + ":synchronizedMethod1……"); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 非同步普通方法2 */ public void method2() { System.out.println(Thread.currentThread().getName() + ":synchronizedMethod2"); } /** * 同步代碼塊1 */ public void synchronizedCodes1() { try { synchronized (this) { System.out.println(Thread.currentThread().getName() + ":synchronizedCodes1"); Thread.sleep(2000l); System.out.println(Thread.currentThread().getName() + ":synchronizedCodes1……"); } } catch (InterruptedException e) { e.printStackTrace(); } } /** * 同步代碼塊2 */ public void synchronizedCodes2() { System.out.println(Thread.currentThread().getName() + ":synchronizedCodes2 will begining……"); synchronized (this) { System.out.println(Thread.currentThread().getName() + ":synchronizedCodes2"); } } public static void main(String[] args) { /*測試非同步普通方法 * 第二個線程不會等第一個結束就開始執行了 */ SynchronizeDemo demo = new SynchronizeDemo(); new Thread(new Runnable() { @Override public void run() { demo.method1(); } }).start(); new Thread(new Runnable() { @Override public void run() { demo.method2(); } }).start(); /* 測試同步靜態方法 *第一個方法執行完畢後纔會執行第二個方法 * 除非不是同一個類 */ // new Thread(new Runnable() { // @Override // public void run() { // SynchronizeDemo.synchronizedStaticMethod1(); // } // }).start(); // // new Thread(new Runnable() { // @Override // public void run() { // SynchronizeDemo.synchronizedStaticMethod2(); // } // }).start(); /*測試同步普通方法 * 第一個方法執行完畢纔會執行第二個方法 * 除非不是同一個對象 */ // SynchronizeDemo demo = new SynchronizeDemo(); // new Thread(new Runnable() { // @Override // public void run() { // demo.synchronizedMethod1(); // } // }).start(); // // new Thread(new Runnable() { // @Override // public void run() { // demo.synchronizedMethod2(); // } // }).start(); /*測試同步代碼塊 * 第一個代碼塊執行完纔會執行第二個代碼塊 * 除非不是同一個對象 */ // SynchronizeDemo demo = new SynchronizeDemo(); // new Thread(new Runnable() { // @Override // public void run() { // demo.synchronizedCodes1(); // } // }).start(); // // new Thread(new Runnable() { // @Override // public void run() { // demo.synchronizedCodes2(); // } // }).start(); } }
wait和notify方法測試:
public class ThreadDemo { public synchronized void run() { try { for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " ::" + i); if (2 == i) { this.wait(); } } } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void run1() { try { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } this.notify(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { ThreadDemo demo = new ThreadDemo(); new Thread(new Runnable() { @Override public void run() { demo.run(); } }).start(); new Thread(new Runnable() { @Override public void run() { demo.run1(); } }).start(); } } 結果以下: Thread-0 ::0 Thread-0 ::1 Thread-0 ::2 Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 Thread-0 ::3 Thread-0 ::4
join方法測試:
public class ThreadJoinDemo { public synchronized void runDemo(String threadName, int i) { System.out.println(threadName + ":" + i); } public static void main(String[] args) throws InterruptedException { ThreadJoinDemo demo = new ThreadJoinDemo(); // 定義子線程 Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { demo.runDemo(Thread.currentThread().getName(), i); } } }); for (int i = 0; i < 5; i++) { demo.runDemo(Thread.currentThread().getName(), i); if (2 == i) { thread.start(); //讓主線程釋放鎖,子線程得到對象鎖並執行完後纔會接着執行主線程未完的操做 thread.join(); } } } } 結果以下: main 0 main 1 main 2 Thread-0:0 Thread-0:1 Thread-0:2 Thread-0:3 Thread-0:4 main 3 main 4