多執行緒2
阿新 • • 發佈:2022-03-27
執行緒常用方法
public class ThreadMethod01 { public static void main(String[] args) throws InterruptedException { //測試相關的方法 T t = new T(); t.setName("老韓"); t.setPriority(Thread.MIN_PRIORITY);//1 t.start();//啟動子執行緒 //主執行緒列印5 hi ,然後我就中斷 子執行緒的休眠 for(intView Codei = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("hi " + i); } System.out.println(t.getName() + " 執行緒的優先順序 =" + t.getPriority());//1 t.interrupt();//當執行到這裡,就會中斷 t執行緒的休眠. } } class T extends Thread { //自定義的執行緒類 @Override public voidrun() { while (true) { for (int i = 0; i < 100; i++) { //Thread.currentThread().getName() 獲取當前執行緒的名稱 System.out.println(Thread.currentThread().getName() + " 吃包子~~~~" + i); } try { System.out.println(Thread.currentThread().getName()+ " 休眠中~~~"); Thread.sleep(20000);//20秒 } catch (InterruptedException e) { //當該執行緒執行到一個interrupt 方法時,就會catch 一個 異常, 可以加入自己的業務程式碼 //InterruptedException 是捕獲到一箇中斷異常. System.out.println(Thread.currentThread().getName() + "被 interrupt了"); } } } }
public class ThreadMethod02 { public static void main(String[] args) throws InterruptedException { T2 t2 = new T2(); t2.start(); for(int i = 1; i <= 20; i++) { Thread.sleep(1000); System.out.println("主執行緒(小弟) 吃了 " + i + " 包子"); if(i == 5) { System.out.println("主執行緒(小弟) 讓 子執行緒(老大) 先吃"); //join, 執行緒插隊 //t2.join();// 這裡相當於讓t2 執行緒先執行完畢 Thread.yield();//禮讓,不一定成功.. System.out.println("執行緒(老大) 吃完了 主執行緒(小弟) 接著吃.."); } } } } class T2 extends Thread { @Override public void run() { for (int i = 1; i <= 20; i++) { try { Thread.sleep(1000);//休眠1秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("子執行緒(老大) 吃了 " + i + " 包子"); } } }View Code
使用者執行緒和守護執行緒
設定守護執行緒
public class ThreadMethod03 { public static void main(String[] args) throws InterruptedException { MyDaemonThread myDaemonThread = new MyDaemonThread(); //如果我們希望當main執行緒結束後,子執行緒自動結束 //,只需將子執行緒設為守護執行緒即可 myDaemonThread.setDaemon(true); myDaemonThread.start(); for( int i = 1; i <= 10; i++) {//main執行緒 System.out.println("寶強在辛苦的工作..."); Thread.sleep(1000); } } } class MyDaemonThread extends Thread { public void run() { for (; ; ) {//無限迴圈 try { Thread.sleep(1000);//休眠1000毫秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("馬蓉和宋喆快樂聊天,哈哈哈~~~"); } } }View Code
執行緒的生命週期: 一般為五大態,新建,就緒,執行,阻塞,死亡
多執行緒買票,導致票量溢位
解決方法:
public class SellTicket { public static void main(String[] args) { SellTicket03 sellTicket03 = new SellTicket03(); new Thread(sellTicket03).start();//第1個執行緒-視窗 new Thread(sellTicket03).start();//第2個執行緒-視窗 new Thread(sellTicket03).start();//第3個執行緒-視窗 } } //實現介面方式, 使用synchronized實現執行緒同步 class SellTicket03 implements Runnable { private int ticketNum = 100;//讓多個執行緒共享 ticketNum private boolean loop = true;//控制run方法變數 Object object = new Object(); //同步方法(靜態的)的鎖為當前類本身 //老韓解讀 //1. public synchronized static void m1() {} 鎖是加在 SellTicket03.class //2. 如果在靜態方法中,實現一個同步程式碼塊. /* synchronized (SellTicket03.class) { System.out.println("m2"); } */ public synchronized static void m1() { } public static void m2() { synchronized (SellTicket03.class) { System.out.println("m2"); } } //老韓說明 //1. public synchronized void sell() {} 就是一個同步方法 //2. 這時鎖在 this物件 //3. 也可以在程式碼塊上寫 synchronize ,同步程式碼塊, 互斥鎖還是在this物件 public /*synchronized*/ void sell() { //同步方法, 在同一時刻, 只能有一個執行緒來執行sell方法 synchronized (/*this*/ object) { if (ticketNum <= 0) { System.out.println("售票結束..."); loop = false; return; } //休眠50毫秒, 模擬 try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("視窗 " + Thread.currentThread().getName() + " 售出一張票" + " 剩餘票數=" + (--ticketNum));//1 - 0 - -1 - -2 } } @Override public void run() { while (loop) { sell();//sell方法是一共同步方法 } } }View Code
死鎖模擬
public class DeadLock_ { public static void main(String[] args) { //模擬死鎖現象 DeadLockDemo A = new DeadLockDemo(true); A.setName("A執行緒"); DeadLockDemo B = new DeadLockDemo(false); B.setName("B執行緒"); A.start(); B.start(); } } //執行緒 class DeadLockDemo extends Thread { static Object o1 = new Object();// 保證多執行緒,共享一個物件,這裡使用static static Object o2 = new Object(); boolean flag; public DeadLockDemo(boolean flag) {//構造器 this.flag = flag; } @Override public void run() { //下面業務邏輯的分析 //1. 如果flag 為 T, 執行緒A 就會先得到/持有 o1 物件鎖, 然後嘗試去獲取 o2 物件鎖 //2. 如果執行緒A 得不到 o2 物件鎖,就會Blocked //3. 如果flag 為 F, 執行緒B 就會先得到/持有 o2 物件鎖, 然後嘗試去獲取 o1 物件鎖 //4. 如果執行緒B 得不到 o1 物件鎖,就會Blocked //A拿到o1,B拿到o2,兩者互不相讓 if (flag) { synchronized (o1) {//物件互斥鎖, 下面就是同步程式碼 System.out.println(Thread.currentThread().getName() + " 進入1"); synchronized (o2) { // 這裡獲得li物件的監視權 System.out.println(Thread.currentThread().getName() + " 進入2"); } } } else { synchronized (o2) { System.out.println(Thread.currentThread().getName() + " 進入3"); synchronized (o1) { // 這裡獲得li物件的監視權 System.out.println(Thread.currentThread().getName() + " 進入4"); } } } } }View Code