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

  • 相关阅读:
    Kafka 生产者 自定义分区策略
    同步互斥
    poj 1562 Oil Deposits(dfs)
    poj 2386 Lake Counting(dfs)
    poj 1915 KnightMoves(bfs)
    poj 1664 放苹果(dfs)
    poj 1543 Perfect Cubes (暴搜)
    poj 1166 The Clocks (暴搜)
    poj 3126 Prime Path(bfs)
    处理机调度
  • 原文地址:https://www.cnblogs.com/pony1223/p/9461000.html
Copyright © 2011-2022 走看看