线程通信

线程通信方式:
  1. 文件共享
  2. 网络通信
  3. 共享变量
  4. jdk提供的协调api:wait/notify,park/unpark。多用于多线程协调完成某一任务。
wait()/notify和park()/unpark()的区别

wait()和notify()是基于锁,调用wait()和notify()方法必须获得对象锁。park()/unpark()则不是,但是park()无法释放锁。

wait()和notify()实现生产者消费者模式
public class StopTest {
    static class BAOZI{
        public int count=0;
    }
    public static void main(String[] args) throws InterruptedException {
        BAOZI count = new BAOZI();
        Producter producter = new Producter();
        producter.setCount(count);
        consume consume = new consume();
        consume.setCount(count);
        consume.start();
        producter.start();

    }
}


    class Producter extends Thread {
    private StopTest.BAOZI count;

        public void setCount(StopTest.BAOZI count) {
            this.count = count;
        }

        @Override
        public void run() {
            while (true) {

                synchronized (count) {
                    while(count.count>0){
                        try {
                            count.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                        count.count++;
                        System.out.println("生产第" + count.count + "个包子");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        count.notifyAll();
                }
            }
        }
    }

    class consume extends Thread {
        public void setCount(StopTest.BAOZI count) {
            this.count = count;
        }

        private StopTest.BAOZI count;
        @Override
        public void run() {
            while (true) {

                synchronized (count) {

                 while (count.count<=0) {
                     try {
                         count.wait();
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                 }
                        System.out.println("消费了第" + count.count + "个包子");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        count.count--;
                        count.notifyAll();

                }
            }
        }
    }

注意:在以上代码中有几个小小主要注意的点,首先判断是否wait()中需要使用while而不是if,原因是可能存在伪唤醒的情况,伪唤醒是有更为底层的指令造成的唤醒而不是因为调用了notify唤醒。其次为什么我要用一个包装类来实现计数,原因是如果直接用Integer类型,因为Integer类型的缓存原因,当我们++的时候其实指向的是应力仪对象了,结果就是会造成报错。类似的如果是Boolean或者String这种带有初始值的也是,修改了之后就是另一个对象了。

你可能感兴趣的:(线程通信)