zoukankan      html  css  js  c++  java
  • Java并发编程原理与实战二十一:线程通信wait&notify&join

    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并发编程实战》龙果学院

  • 相关阅读:
    Android开发进阶——自定义View的使用及其原理探索
    Android开发——通过wifi接收IPCamera视频流
    (数据科学学习手札84)基于geopandas的空间数据分析——空间计算篇(上)
    (数据科学学习手札83)基于geopandas的空间数据分析——geoplot篇(下)
    (数据科学学习手札82)基于geopandas的空间数据分析——geoplot篇(上)
    (数据科学学习手札81)conda+jupyter玩转数据科学环境搭建
    (数据科学学习手札80)用Python编写小工具下载OSM路网数据
    (数据科学学习手札79)基于geopandas的空间数据分析——深入浅出分层设色
    实用的Python(3)超简单!基于Python搭建个人“云盘”
    (数据科学学习手札78)基于geopandas的空间数据分析——基础可视化
  • 原文地址:https://www.cnblogs.com/pony1223/p/9461000.html
Copyright © 2011-2022 走看看