1. 程式人生 > >java 多執行緒等待、喚醒機制例項

java 多執行緒等待、喚醒機制例項

例子:

1、實體類

public class Student {
    String name;
    int age;
    boolean flag = false; // 表示沒有值
}

2、執行緒1

public class SetThread implements Runnable {

    private Student s;
    private int x = 0;

    public SetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (s) {
                // 判斷,如果有值,就等待
                if (s.flag) {
                    try {
                        s.wait(); //t1就等待在這裡了。
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                // 設定值
                if (x % 2 == 0) {
                    s.name = "林青霞";
                    s.age = 27;
                } else {
                    s.name = "劉意";
                    s.age = 30;
                }
                x++; //x=1,x=2,

                // 有值後,就修改標記
                s.flag = true;
                s.notify(); // 喚醒等待的執行緒,喚醒其他的執行緒,不代表其他的執行緒能夠立即執行。
            }
            //可能t1搶到,也可能t2搶到
        }
    }

}

3、執行緒2

public class GetThread implements Runnable {

    private Student s;

    public GetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (s) {
                // 判斷沒有值,就等待
                if (!s.flag) {
                    try {
                        s.wait(); //t2在這等待了。
                                  //t2執行緒在這裡等待,那麼,它就會釋放鎖物件。
                                  //將來,當它再次獲取到執行權的時候,是從哪裡等待,哪裡醒來。
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println(s.name + "---" + s.age);
                //林青霞---27

                // 修改標記
                s.flag = false;
                s.notify(); //喚醒其他的執行緒
            }
            //可能t2,可能t1
        }
    }

}

4、測試程式碼

/*
 * 需求:我有一個學生,我可以對其屬性設定值,我也可以獲取其屬性值。請用執行緒間通訊的案例來體現。
 *
 * 資源:Student
 * 設定執行緒:SetThread
 * 獲取執行緒:GetThread
 * 測試類:StudentDemo
 *
 * 剛才的資料是大片大片出現的。我想把這個動作改進為依次出現的資料。
 * 怎麼辦呢?
 *         原理:如果我的學生屬性沒有值,我應該先賦值,然後才能使用。
 *              如果學生的屬性有值,應該使用後再賦值。
 *
 * 為了配合這個操作,java提供了一種機制:等待喚醒機制。
 *         notify()
 *         wait()
 *         這兩個方法的呼叫應該通過鎖物件去使用。
 */
public class StudentDemo {
    public static void main(String[] args) {
        // 建立一個資源
        Student s = new Student();

        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

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