多线程通信

什么是多线程的通信?

        多线程对同一共享资源的不同操作。

wait()

      wait方法将当前的线程挂起,并释放出锁资源。wait方法属于Object类中。

此方法应始终在循环中使用:

synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
     }
 

此方法只应由作为此对象监视器的所有者的线程来调用。

package com.cn.test.thread;

public class TestWait extends Thread{

    Object obj = new Object();
    
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
               System.out.println("running start");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("running over");
            }
        }
    public static void main(String[] args) {

        TestWait testWait = new TestWait();
        testWait.start();
    }

}

此方法必须同sychnorized同时使用,不使用sychnorized直接调用此方法发生异常:

running start
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.cn.test.thread.TestWait.run(TestWait.java:12)

package com.cn.test.thread;

public class TestWait extends Thread{

    Object obj = new Object();
    
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("running start");
            synchronized (obj) {
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("running over");
            }
        }
    }
    public static void main(String[] args) {

        TestWait testWait = new TestWait();
        testWait.start();
    }

}

运行结果:线程一直处于阻塞的状态

running start

obj.wait(long time); 

该方法挂去time长的时间,时间已过,线程又处于竞争cpu的资源中、

此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调度目的,在发生以下四种情况之一前,线程 T 被禁用,且处于休眠状态:

    • 其他某个线程调用此对象的 notify 方法,并且线程 T 碰巧被任选为被唤醒的线程。
    • 其他某个线程调用此对象的 notifyAll 方法。
    • 其他某个线程中断线程 T
    • 大约已经到达指定的实际时间。但是,如果 timeout 为零,则不考虑实际时间,在获得通知前该线程将一直等待。

notify()唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。notifyAll()唤醒当前等待的所有的线程。

notifyAll()唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待。

例子: 生产者消费者,生产者写入数据,消费者进行消费数据

package com.cn.test.thread;

public class Resource {
     public String name;
     public String color;
     public boolean sychFlag = true; //同步标识
}
package com.cn.test.thread;

public class Customer extends Thread{

    private Resource res;
    Customer(Resource res) {
        this.res = res;
    }
    
    @Override
    public void run() {
        while (true) {
            synchronized (res) {
                if (!res.sychFlag) {
                    // 消费者进行消费
                    System.out.println("name=" + res.name + "color =" + res.color);
                    // 消费者消费完毕
                    res.sychFlag = true;
                    // 阻塞当前的线程
                    res.notifyAll();

                } else {
                    try {
                        res.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
package com.cn.test.thread;

public class Producer extends Thread{

    private Resource res;
    Producer(Resource res) {
        this.res = res;
    }
    @Override
    public void run() {
        /**
         * 同步标识为true生产者开始进行生产
         * 消费者进行等待
         */
        int count = 0;
        while (true) {
            synchronized (res) {
                if (res.sychFlag) {
                    // 生产者进行生产
                    if (count % 2 == 0) {
                        res.name = "张三";
                        res.color = "blue";
                    } else {
                        res.name = "尤其";
                        res.color = "red";
                    }
                    count++;
                    res.sychFlag = false;
                    // 写完之后唤醒当前的线程
                    res.notifyAll();
                } else {
                    // 阻塞当前线程,并且释放锁的资源
                    try {
                        res.wait();
                        Thread.sleep(100);
                        System.out.println("我被挂起了");
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
}
package com.cn.test.thread;

public class TestMain {

    public static void main(String[] args) {
           Resource res = new Resource();
        Producer p = new Producer(res);
        Producer p2 = new Producer(res);
        Customer c = new Customer(res);
        Customer c1 = new Customer(res);
        c.start();
    //    c1.start();
        p.start();
    //    p2.start();
    }

}