一.Java線程具有五中基本狀態
新建狀態(New):當線程對象對創建后,即進入了新建狀態,如:Thread t = new MyThread();
就緒狀態(Runnable):當調用線程對象的start()方法(t.start();),線程即進入就緒狀態。處於就緒狀態的線程,只是說明此線程已經做好了准備,隨時等待CPU調度執行,並不是說執行了t.start()此線程立即就會執行;
運行狀態(Running):當CPU開始調度處於就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。注:就 緒狀態是進入到運行狀態的唯一入口,也就是說,線程要想進入運行狀態執行,首先必須處於就緒狀態中;
阻塞狀態(Blocked):處於運行狀態中的線程由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才 有機會再次被CPU調用以進入到運行狀態。根據阻塞產生的原因不同,阻塞狀態又可以分為三種:
1.等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態;
2.同步阻塞 -- 線程在獲取synchronized同步鎖失敗(因為鎖被其它線程所占用),它會進入同步阻塞狀態;
3.其他阻塞 -- 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。
二. Java多線程的創建及啟動
1.繼承Thread類,重寫該類的run()方法。
兩個線程同時運行,隨機產生4位隨機字符

1 import java.util.Random; 2 3 public class 多線程 { 4 5 public static Object lock = new Object(); 6 7 public static void randomString() { 8 String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 9 Random random = new Random(); 10 StringBuffer sb = new StringBuffer(); 11 for (int i = 0; i < 4; i++) { 12 int number = random.nextInt(62); 13 sb.append(str.charAt(number)); 14 } 15 System.out.print(sb); 16 } 17 18 public static void main(String[] args) { 19 20 new Thread(new myTh1()).start(); 21 new Thread(new myTh2()).start(); 22 23 } 24 25 } 26 27 class myTh1 extends Thread { 28 @Override 29 public void run() { 30 while (true) { 31 32 try { 33 synchronized (多線程.lock) { 34 多線程.randomString(); 35 System.out.print("------"+Thread.currentThread().getName()); 36 System.out.println(); 37 } 38 sleep(1000); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } 42 } 43 } 44 } 45 46 class myTh2 extends Thread { 47 @Override 48 public void run() { 49 while (true) { 50 try { 51 synchronized (多線程.lock) { 52 多線程.randomString(); 53 System.out.print("------"+Thread.currentThread().getName()); 54 System.out.println(); 55 } 56 sleep(1000); 57 } catch (InterruptedException e) { 58 e.printStackTrace(); 59 } 60 } 61 } 62 }
2.實現Runnable接口,並重寫該接口的run()方法,該run()方法同樣是線程執行體,創建Runnable實現類的實例,並以此實例作為Thread類的target來創建Thread對象,該Thread對象才是真正的線程對象
主線程和兩個實現Runnable接口的線程同時運行,線程對象只運行5次。

1 public class 多線程Runnable { 2 3 public static void main(String[] args) { 4 System.out.println(Thread.currentThread().getName()); 5 try { 6 Thread.sleep(3000); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 } 10 11 new Thread(new myTh3()).start(); 12 new Thread(new myTh4()).start(); 13 14 15 } 16 } 17 class myTh3 extends Thread{ 18 int i=0; 19 @Override 20 public void run() { 21 while (i<5) { 22 System.out.println(Thread.currentThread().getName()); 23 try { 24 sleep(2000); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 i++; 29 } 30 31 } 32 33 } 34 35 class myTh4 implements Runnable{ 36 37 int i=0; 38 @Override 39 public void run() { 40 while (i<5) { 41 System.out.println(Thread.currentThread().getName()); 42 i++; 43 } 44 45 } 46 }
3.synchronized, wait, notify結合:
解決問題三個人去買票,張某有20元,李某10元。趙某5元。電影票5元一張,售貨員只有3張5元的
1 /*問題: 2 * 三個人去買票,張某有20元,李某10元。趙某5元。 3 * 電影票5元一張,售貨員只有3張5元的。 4 * 5 * 思路: 6 * 張某買了票就會少3張5元的 7 * 李某買了票就會少1張5元的 8 * 趙某買了票就會多1張5元的 9 * 所以有三種情況: 10 * 一。趙某先買,張李都可以買 11 * 二。張某先買,此時李某買不了,只能等待趙某買了,再買 12 * 三。李某先買,此時張某買不了,只能等待趙某買了,再買 13 * 14 * 靜態常量:售貨員總錢數 sum=3 15 * 16 * 1.創建三個線程分別為張某,李某,趙某 17 * 2.判斷此時sum值,合適就買票,減去相應的錢數,不合適就等待。 18 */ 19 import java.util.ArrayList; 20 import java.util.Iterator; 21 import java.util.List; 22 23 public class 多線程3 { 24 25 public static int sum = 3;//設置零錢總張數為3張 26 public static Object look = new Object();//建立一個鎖 27 28 public static List<Thread> arrayList = new ArrayList<>();//建立集合 保存這三個購買人的線程 29 30 public static void main(String[] args) throws InterruptedException { 31 //隨機將趙某李某張某添加到集合中 32 arrayList.add(new li()); 33 arrayList.add(new zhang()); 34 arrayList.add(new zhao()); 35 36 //通過迭代器遍歷集合 37 Iterator<Thread> iterator = arrayList.iterator(); 38 39 while (iterator.hasNext()) { 40 //獲取線程 41 Thread t = iterator.next(); 42 //線程啟動 43 t.start(); 44 //線程睡眠 45 t.sleep(2000); 46 } 47 48 } 49 } 50 /** 51 * 張某線程 52 * @author Administrator 53 * 54 */ 55 class zhang extends Thread { 56 @Override 57 public void run() { 58 //因為要判斷等待和喚醒,並且操作sum,所以在此處加鎖 59 synchronized (多線程3.look) { 60 while (多線程3.sum < 3) { 61 try { 62 System.out.println("因為此時零錢不足:"+多線程3.sum+"張"); 63 System.out.println("所以張某沒買到電影票,等待購買"); 64 多線程3.look.wait(); 65 } catch (InterruptedException e) { 66 e.printStackTrace(); 67 } 68 } if (多線程3.sum > 2) { 69 多線程3.sum = 多線程3.sum - 3; 70 多線程3.look.notify(); 71 System.out.println("張某買到了電影票"); 72 System.out.println("此時零錢數為:"+多線程3.sum+"張"); 73 } 74 } 75 } 76 } 77 /** 78 * 李某線程 79 * @author Administrator 80 * 81 */ 82 class li extends Thread { 83 @Override 84 public void run() { 85 synchronized (多線程3.look) { 86 while (多線程3.sum < 1) { 87 try { 88 System.out.println("因為此時零錢不足:"+多線程3.sum+"張"); 89 System.out.println("所以李某沒買到電影票,等待購買"); 90 多線程3.look.wait(); 91 } catch (InterruptedException e) { 92 e.printStackTrace(); 93 } 94 } if (多線程3.sum >= 1) { 95 多線程3.sum = 多線程3.sum - 1; 96 多線程3.look.notify(); 97 System.out.println("李某買到了電影票"); 98 System.out.println("此時零錢數為:"+多線程3.sum+"張"); 99 } 100 101 } 102 } 103 } 104 /** 105 * 趙某線程 106 * @author Administrator 107 * 108 */ 109 class zhao extends Thread { 110 @Override 111 public void run() { 112 synchronized (多線程3.look) { 113 if (多線程3.sum >= 0) { 114 多線程3.sum = 多線程3.sum + 1; 115 System.out.println("趙某買到了電影票"); 116 System.out.println("此時零錢數為:"+多線程3.sum+"張"); 117 多線程3.look.notify(); 118 } 119 } 120 } 121 }
全部都是培訓課后習題,最后一個足足搞了半天,希望我寫的沒毛病,求指教。。謝謝大佬。