執行緒(2)

爱要用心码,不要说话發表於2024-07-06

1. Thread類中常用的一些方法

  • 執行緒休眠方法-static void sleep
public class MyThread extends Thread{

    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            try {
                //秒殺---
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(Thread.currentThread().getName()+"~~~~~~~~~~~~~~~"+i);
        }
    }
}
  • yield 當前執行緒讓出cpu-參與下次的競爭
public class MyThread extends Thread{

    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            System.out.println(Thread.currentThread().getName()+"~~~~~~~~~~~~~~~"+i);
            Thread.yield();//當前執行緒讓出cpu參與下次的競爭。
            System.out.println("~~~~~~~~~~~~~~~~");
        }
    }
}
  • join加入當前執行緒上
public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyThread t1=new MyThread();
        t1.setName("執行緒A");
        MyThread2 t2=new MyThread2();
        t2.setName("執行緒B");


        t1.start();
        t2.start();

        t1.join(); //t1加入主執行緒上,主執行緒需要等t1執行完畢後才會執行. 如果主執行緒需要等帶t1和t2執行緒的執行結果 做下一步操作時。
        for (int i = 0; i <20 ; i++) {
            Thread.sleep(10);
            System.out.println("main~~~~~~~~~~~~~~~~~~~~~"+i);
        }
    }
}
  • setDaemon()設定執行緒為守護執行緒
//JDK--預設就有一個守護執行緒.GC垃圾回收。
public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyThread t1=new MyThread();
        t1.setName("執行緒A");
        t1.setDaemon(true);//設定t1為守護執行緒
        t1.start();
        for (int i = 0; i <20 ; i++) {
            System.out.println("main~~~~~~~~~~~~~~~~~~~~~"+i);
        }
    }
}

2. 解決執行緒安全問題

什麼情況下會出現執行緒安全問題

當多個執行緒操作同一個資源時,則出現執行緒安全問題。

  • java如何解決執行緒安全問題

提供了兩種方式:第一種:使用synchronized自動鎖 第二種: 使用Lock手動鎖。

使用鎖相對於把原來的非同步轉換為同步操作。

  • 使用synchronized關鍵字解決

它可以使用在方法上,也可以使用在程式碼塊中。
synchronized(共享鎖物件){
同步程式碼塊。

}

public class SellTicket implements Runnable {
    private int tick = 100;
    private static Object o = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                if (tick > 0) {
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    tick--;
                    System.out.println(Thread.currentThread().getName() + "賣了一張票;剩餘:" + tick + "張");
                } else {
                    break;
                }
            }
        }
    }
}
 public synchronized void sell(){
        if (tick > 0) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            tick--;
            System.out.println(Thread.currentThread().getName() + "賣了一張票;剩餘:" + tick + "張");
        }
    }
  • 使用Lock手動

Lock它是一個介面,它的實現類。ReentrantLock

public class SellTicket implements Runnable {
    private int tick = 100;

    private Lock l = new ReentrantLock();

    //synchronized使用在方法那麼它的共享鎖為this
    @Override
    public void run() {
        while (true) {
            try {
                l.lock();//加鎖
                if (tick > 0) {
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    tick--;
                    System.out.println(Thread.currentThread().getName() + "賣了一張票;剩餘:" + tick + "張");
                } else {
                    break;
                }
            } finally {
                l.unlock();//解鎖
            }
        }
    }
}
  • synchronized和lock區別

synchronized可以使用程式碼塊和方法。自動加鎖和釋放鎖。不會出現死鎖問題。

lock它只能使用在程式碼塊中。需要手動加鎖和釋放鎖。如果不釋放鎖,死鎖問題。靈活。它的釋放鎖必須放在finally.

3. 死鎖

執行緒A擁有鎖資源a,希望獲取鎖資源b,執行緒B擁有鎖資源b,希望獲取鎖資源a。 兩個執行緒互相擁有對方希望獲取的鎖資源。可能會出現程式堵塞。從而造成死鎖。

1. 不要使用鎖巢狀。
2. 設定超時時間。--Lock類中tryLock.
3. 使用安全java.util.concurrent下的類。

4. 執行緒狀態

    NEW,====新建狀態。
    RUNNABLE,===>就緒狀態和執行狀態
    BLOCKED,===>堵塞狀態
    WAITING,====>等待狀態
    TIMED_WAITING,===>時間等待
    TERMINATED;===終止。

相關文章