1. 這裏我推薦下陸先生的Java代碼質量改進之:同步對象的選擇這篇博文。html
2. 以上推薦的博文是以賣火車票爲例,引出了非同步會致使的錯誤以及同步鎖(監視器)應該若是選擇,應該可以幫助你們理解同步鎖。java
1. 這裏我推薦下Java中synchronized同步鎖用法及做用範圍這篇博文。編程
2. 以上的博文將靜態鎖(字節碼文件鎖)和非靜態鎖(this)進行了對比,以及將線程非同步和線程同步下進行了對比,對你們瞭解線程鎖的用法和做用範圍有很大的幫助。多線程
1. 這裏我推薦下java中線程同步的理解(很是通俗易懂)這篇博文。ide
2. 以上推薦的博文以很是通俗易懂的觀點解釋了到時什麼同步,將同步理解成了線程同步就是線程排隊,並且舉了一些平常生活中的例子來讓你們理解到底什麼是同伴。學習
1. 並非說同步在什麼狀況下都是好的,由於線程的同步會帶來較低效率,由於線程同步就表明着線程要排隊,即線程同步鎖會帶來的同步阻塞狀態。this
2. 由於CPU是隨意切換線程的,當咱們想讓當前線程執行以後CPU不隨意切換到其餘線程,或者咱們想要讓某個線程的代碼可以在徹底執行以前不會被搶奪執行權,不會致使從而沒法連續執行,那麼咱們就須要線程的幫助。spa
1.sleep方法的基本用法.net
Thread.sleep(long millis),傳入毫秒數(1秒 = 1000毫秒),在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操做受到系統計時器和調度程序精度和準確性的影響。該線程不丟失任何監視器的所屬權。(~注:Java技術文檔的意思就是該線程休眠指定的毫秒數,並且休眠狀態暫時失去CPU執行權,並且線程醒來後,該線程不會釋放鎖。)線程
1 /** 2 * 3 * Thread.sleep的計時器用法 4 * 5 */ 6 public class ThreadSleepTest { 7 8 public static void main(String[] args) { 9 new Thread() { 10 @Override 11 public void run() { 12 int timeCount = 10; 13 while (timeCount >= 0) { 14 if (timeCount == 0) { 15 System.out.println("新年快樂!~"); 16 break; 17 } 18 System.out.println("還剩" + timeCount-- + "秒"); 19 try { 20 Thread.sleep(1000); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 } 25 } 26 }.start(); 27 } 28 29 }
2.sleep方法使用的位置選擇
我在使用sleep方法時發現,當sleep的位置不一致所放的位置不一樣時,線程所運行的結果也是大不相同的,如下的代碼是爲了舉例子,並非說這個同步代碼塊就是應這樣寫(其實這段代碼這麼寫是有很大的問題的,由於同步資源的選擇不許確),至於同步資源的選擇我在第二個大問題會講到。
1 package javase.week4; 2 3 public class SellTrainTickets { 4 5 public static void main(String[] args) { 6 new MyThread("窗口1").start(); 7 new MyThread("窗口2").start(); 8 new MyThread("窗口3").start(); 9 new MyThread("窗口4").start(); 10 } 11 12 } 13 14 class MyThread extends Thread { 15 16 static int tickets = 100; 17 18 public MyThread(String name) { 19 super(name); 20 } 21 22 @Override 23 public void run() { 24 while (tickets > 0) {//假設這已經減到了1 1>0 而後窗口1 窗口2 窗口3 窗口4 都進入循環 25 try { 26 Thread.sleep(20); 27 28 } catch (InterruptedException e) { 29 e.printStackTrace(); 30 } 31 synchronized (MyThread.class) { 32 System.out.println(getName() + "賣出了第" + tickets-- + "張票!");//而後0 -1 -2 -3,這時就出現了負票 33 } 34 } 35 } 36 }
1 public class SellTrainTickets { 2 3 public static void main(String[] args) { 4 new MyThread("窗口1").start(); 5 new MyThread("窗口2").start(); 6 new MyThread("窗口3").start(); 7 new MyThread("窗口4").start(); 8 } 9 10 } 11 12 class MyThread extends Thread { 13 14 static int tickets = 100; 15 16 public MyThread(String name) { 17 super(name); 18 } 19 20 @Override 21 public void run() { 22 while (tickets > 0) {//假設這已經減到了0 5>0 而後窗口1 窗口2 窗口3 窗口4 都進入循環 23 synchronized (MyThread.class) { 24 System.out.println(getName() + "賣出了第" + tickets-- + "張票!");//而後 3 2 1 0 25 } 26 try { 27 Thread.sleep(20);//此時票數等於0,這時窗口1 窗口2 窗口3 窗口4 都處於休眠,而後若是這裏的時間合理的話,再次判斷的話,正好在等於0的時候,都沒有線程再次進入循環,也就不會出現負票了 28 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 }
3.sleep方法的傳入參數的選擇
sleep方法的傳入的毫秒數對於線程的運行結果是有較大的影響的,最直接簡單的影響就是讓運行延遲了,可是除了這個之外其實也讓線程的運行結果發生了變化,順便分享一篇一篇高質量的博文Sleep(0)的妙用。
1 public class TicketsThreadTest { 2 3 public static void main(String[] args) { 4 new TicketThread("窗口1").start(); 5 new TicketThread("窗口2").start(); 6 new TicketThread("窗口3").start(); 7 new TicketThread("窗口4").start(); 8 } 9 10 } 11 12 class TicketThread extends Thread { 13 14 public TicketThread(String name) { 15 super(name); 16 } 17 18 private static int ticket = 100; 19 20 public void run() { 21 while (true) { 22 synchronized (TicketThread.class) { 23 if (ticket <= 0) { 24 break; 25 } 26 System.out.println(getName() + "賣出了第" + ticket-- + "張票!"); 27 try { 28 Thread.sleep(100); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 } 35 }
1 public class TicketsThreadTest { 2 3 public static void main(String[] args) { 4 new TicketThread("窗口1").start(); 5 new TicketThread("窗口2").start(); 6 new TicketThread("窗口3").start(); 7 new TicketThread("窗口4").start(); 8 } 9 10 } 11 12 class TicketThread extends Thread { 13 14 public TicketThread(String name) { 15 super(name); 16 } 17 18 private static int ticket = 100; 19 20 public void run() { 21 while (true) { 22 synchronized (TicketThread.class) { 23 if (ticket <= 0) { 24 break; 25 } 26 System.out.println(getName() + "賣出了第" + ticket-- + "張票!"); 27 try { 28 Thread.sleep(1); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 } 35 }
若是這裏同步的是代碼塊不是代碼方法,那麼這裏須要對要同步的共享資源的選擇要準確,若是選擇得不許確會致使結果不理想。
1 public class TicketsThreadTest { 2 3 public static void main(String[] args) { 4 new TicketThread("窗口1").start(); 5 new TicketThread("窗口2").start(); 6 new TicketThread("窗口3").start(); 7 new TicketThread("窗口4").start(); 8 } 9 10 } 11 12 class TicketThread extends Thread { 13 14 public TicketThread(String name) { 15 super(name); 16 } 17 18 private static int ticket = 100; 19 20 public void run() { 21 while (true) { 22 if (ticket <= 0) { 23 break; 24 } 25 synchronized (TicketThread.class) { 26 System.out.println(getName() + "賣出了第" + ticket-- + "張票!"); 27 } 28 try { 29 Thread.sleep(0); 30 } catch (InterruptedException e) { 31 e.printStackTrace(); 32 } 33 } 34 } 35 }
1 public class TicketsThreadTest { 2 3 public static void main(String[] args) { 4 new TicketThread("窗口1").start(); 5 new TicketThread("窗口2").start(); 6 new TicketThread("窗口3").start(); 7 new TicketThread("窗口4").start(); 8 } 9 10 } 11 12 class TicketThread extends Thread { 13 14 public TicketThread(String name) { 15 super(name); 16 } 17 18 private static int ticket = 100; 19 20 public void run() { 21 while (true) { 22 synchronized (TicketThread.class) { 23 if (ticket <= 0) { 24 break; 25 } 26 System.out.println(getName() + "賣出了第" + ticket-- + "張票!"); 27 try { 28 Thread.sleep(0); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 } 35 }
1 package javase.week4; 2 3 /** 4 * 5 * 三個線程之間的通訊使用if選擇語句 6 * 7 */ 8 public class ComunicatedThreadTest { 9 public static void main(String[] args) { 10 Printer1121 p = new Printer1121(); 11 new Thread() { 12 @Override 13 public void run() { 14 while (true) { 15 try { 16 p.print1(); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 } 20 } 21 } 22 }.start(); 23 new Thread() { 24 @Override 25 public void run() { 26 while (true) { 27 try { 28 p.print2(); 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 }.start(); 35 36 new Thread() { 37 @Override 38 public void run() { 39 while (true) { 40 try { 41 p.print3(); 42 } catch (Exception e) { 43 e.printStackTrace(); 44 } 45 } 46 } 47 }.start(); 48 } 49 50 } 51 52 class Printer1121 { 53 private int flag = 1; 54 55 public void print1() throws Exception { 56 synchronized (this) { 57 if (flag != 1) { 58 this.wait(); 59 } 60 Thread.sleep(100); 61 System.out.print(1); 62 System.out.print(2); 63 System.out.print(3); 64 System.out.print(4); 65 System.out.print(5); 66 System.out.println(); 67 flag = 2; 68 this.notifyAll(); 69 } 70 } 71 72 public void print2() throws Exception { 73 synchronized (this) { 74 if (flag != 2) { 75 this.wait(); 76 } 77 Thread.sleep(100); 78 System.out.print("a"); 79 System.out.print("b"); 80 System.out.print("c"); 81 System.out.print("d"); 82 System.out.print("e"); 83 System.out.println(); 84 flag = 3; 85 this.notifyAll(); 86 } 87 } 88 89 public void print3() throws Exception { 90 synchronized (this) { 91 if (flag != 3) { 92 this.wait(); 93 } 94 Thread.sleep(100); 95 System.out.print("A"); 96 System.out.print("B"); 97 System.out.print("C"); 98 System.out.print("D"); 99 System.out.print("E"); 100 System.out.println(); 101 flag = 1; 102 this.notifyAll(); 103 } 104 } 105 }
1 package javase.week4; 2 /** 3 * 4 * 三個線程之間的通訊使用while循環判斷語句 5 * 6 */ 7 public class ComunicatedThreadTest { 8 public static void main(String[] args) { 9 Printer1121 p = new Printer1121(); 10 new Thread() { 11 @Override 12 public void run() { 13 while (true) { 14 try { 15 p.print1(); 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } 19 } 20 } 21 }.start(); 22 new Thread() { 23 @Override 24 public void run() { 25 while (true) { 26 try { 27 p.print2(); 28 } catch (Exception e) { 29 e.printStackTrace(); 30 } 31 } 32 } 33 }.start(); 34 35 new Thread() { 36 @Override 37 public void run() { 38 while (true) { 39 try { 40 p.print3(); 41 } catch (Exception e) { 42 e.printStackTrace(); 43 } 44 } 45 } 46 }.start(); 47 } 48 49 } 50 51 class Printer1121 { 52 private int flag = 1; 53 54 public void print1() throws Exception { 55 synchronized (this) { 56 while (flag != 1) { 57 this.wait(); 58 } 59 Thread.sleep(100); 60 System.out.print(1); 61 System.out.print(2); 62 System.out.print(3); 63 System.out.print(4); 64 System.out.print(5); 65 System.out.println(); 66 flag = 2; 67 this.notifyAll(); 68 } 69 } 70 71 public void print2() throws Exception { 72 synchronized (this) { 73 while (flag != 2) { 74 this.wait(); 75 } 76 Thread.sleep(100); 77 System.out.print("a"); 78 System.out.print("b"); 79 System.out.print("c"); 80 System.out.print("d"); 81 System.out.print("e"); 82 System.out.println(); 83 flag = 3; 84 this.notifyAll(); 85 } 86 } 87 88 public void print3() throws Exception { 89 synchronized (this) { 90 while (flag != 3) { 91 this.wait(); 92 } 93 Thread.sleep(100); 94 System.out.print("A"); 95 System.out.print("B"); 96 System.out.print("C"); 97 System.out.print("D"); 98 System.out.print("E"); 99 System.out.println(); 100 flag = 1; 101 this.notifyAll(); 102 } 103 } 104 }