1. 程式人生 > 其它 >多執行緒2

多執行緒2

執行緒常用方法

 

 

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(int
i = 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 void
run() { 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了"); } } } }
View Code

 

 

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