Java並發編程原理與實戰二十一:線程通訊wait&notify&join

來源:互聯網
上載者:User

標籤:new t   class   sum   tac   生產   demo   需要   run   current   

wait和notify

wait和notify可以實現線程之間的通訊,當一個線程執行不滿足條件時可以調用wait方法將線程置為等待狀態,當另一個線程執行到等待線程可以執行的條件時,調用notify可以喚醒等待的線程。需要強調的是,在調用wait和notify時需要先擷取鎖,否則會拋出IllegalMonitorException異常。notify方法隨機從等待的線程中喚醒一個線程執行,notifyAll方法喚醒所有的等待線程,這些線程競爭時間片。下面是一個使用wait和notify的例子:當寫線程將signal喚醒標誌為1時,讀線程才可以讀。

public class Demo {

    private volatile int signal;

    public synchronized int getSignal() {
        System.out.println(Thread.currentThread().getName() + " 進入同步方法了");
        if (signal != 1) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return signal;
    }

    public synchronized void setSignal(int signal) {
        System.out.println(Thread.currentThread().getName() + " 喚醒了");
        this.signal = signal;
        notifyAll();
    }

    public static void main(String[] args) {
        Demo demo = new Demo();
        TaskOne taskOne = new TaskOne(demo);

        TaskTwo taskTwo = new TaskTwo(demo);

        // 開啟讀線程

        new Thread(taskOne).start();
        new Thread(taskOne).start();
        new Thread(taskOne).start();
        new Thread(taskOne).start();

 

        // 開啟寫線程

        new Thread(taskTwo).start();
    }

}

public class TaskOne implements Runnable {

    private Demo demo;

    public TaskOne(Demo demo) {
        this.demo = demo;
    }

    @Override
    public void run() {
        demo.getSignal();
    }
}

public class TaskTwo implements Runnable {

    private Demo demo;

    public TaskTwo(Demo demo) {
        this.demo = demo;
    }

    @Override
    public void run() {
        demo.setSignal(1);
    }

}

2.用wait和notify實現生產者和消費者

public class Table {

    private int count;

    private static final int MAX_COUNT = 10;

    public synchronized void push() {
        while (count >= MAX_COUNT) {
            try {
                System.out.println(Thread.currentThread().getName() + "桌子已放滿,生產者停止生產");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count++;

        System.out.println(Thread.currentThread().getName() + "桌子上當前產品數量: "+ count);

        // 桌上一有產品就喚醒消費者

        notifyAll();
    }

    public synchronized void take() {
        while (count <= 0) {
            try {
                System.out.println(Thread.currentThread().getName() + "桌子已空,消費者停止消費");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count--;

        System.out.println(Thread.currentThread().getName() + "桌上剩餘產品: " + count);

        // 當桌子上的產品被消費完後喚醒生產者

        notifyAll();
    }

}

public class Productor implements Runnable {

    private Table table;

    public Productor(Table table) {
        this.table = table;
    }

    @Override
    public void run() {
        while (true) {
            table.push();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

public class Consumer implements Runnable {

    private Table table;

    public Consumer(Table table) {
        this.table = table;
    }

    @Override
    public void run() {
        while (true) {
            table.take();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

public class Demo {
    public static void main(String[] args) {
        Table table = new Table();
        Productor productor = new Productor(table);
        Consumer consumer = new Consumer(table);

        new Thread(productor).start();
        new Thread(productor).start();
        new Thread(productor).start();
        new Thread(productor).start();

        new Thread(consumer).start();
        new Thread(consumer).start();
        new Thread(consumer).start();
        new Thread(consumer).start();
        new Thread(consumer).start();
        new Thread(consumer).start();
    }
}

2.join

調用join方法的線程會加塞到其他線程之前執行,被加塞的線程在調用join方法的線程執行完後才接著執行。

public class JoinDemo {

    public void a(Thread joinThread) {
        System.out.println("線程a開始執行...");
        joinThread.start();
        try {
            // 當前線程阻塞直到joinThread執行完畢
            joinThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("線程a執行結束...");
    }

    public void b() {
        System.out.println("加塞線程開始執行...");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("加塞線程執行結束...");
    }

    public static void main(String[] args) {
        final JoinDemo demo = new JoinDemo();
        final Thread joinThread = new Thread() {
            @Override
            public void run() {
                demo.b();
            }
        };

        new Thread() {
            @Override
            public void run() {
                demo.a(joinThread);
            }
        }.start();
    }
}

 

參考資料:

《java並發編程實戰》龍果學院

Java並發編程原理與實戰二十一:線程通訊wait&notify&join

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.