Java多线程-线程间通信

一,等待/通知机制  实现线程间的通信

举个例子:我们去饭店就餐,饭店上餐的时间不确定,如果我们一直去询问前台,是不是很烦,我么这时就处于等待(wait)状态,但是 饭店肯定会有人肯定会通知 (notify),那个桌的菜已经做好了,前台就会通知这桌的人,菜来了。

1,主要的方法wait() /notify() 这个两个方法时Object类本地方法 都要在同步方法中调用

          1),wait() 使执行当前代码的线程进行等待,执行完毕后,线程就会释放锁,以便别的线程可以获得锁。

           2),notify(),随机挑选一个处于wait()的线程,让他获得锁,但这个方法不会立即释放当前线程的对象锁,只有程序执行完毕后,才会释放锁。

           3)sleep()方法,这个方法也是不是放锁的 ,那么别的线程要获取这个锁就会处于等待状态。

           4),在调用wait()方法后,使线程处于wait状态,这时如果调用interrupt()就会出现InterrruptedException异常

           5),notify()方法一次只会通知一个线程。notifyAll()通知所有的线程

二,使用等待/通知机制,实现生产者/消费者模式

/**
 * 通知等待机制 实现消费者者/生产者模式
 */
public class PCDemo {
    //消费品
    public static class Data{
        public static String value = " ";
    }
    //生产者
    public static class Producer{
        private String lock;
        public Producer(String value){
            this.lock = value;
        }
        public void setValue() throws Exception{
           synchronized (lock){
               if (!Data.value.equals(" ")){  //说明value没有被消费
                   lock.wait();
               }else{
                   String s = System.currentTimeMillis()+" ";
                   System.out.println("设置的value = " + s+"  当前线程的Name = "+Thread.currentThread().getName());
                   Data.value = s;//生产数据
                   lock.notify();//通知等待的消费者去消费
               }
           }
        }
    }
    //消费者
    public static class Consumer{
        private String lock;
        public Consumer(String lock){
            this.lock = lock;
        }
        public void getValue() throws Exception{
            synchronized (lock){
                if (Data.value.equals(" ")){ //说明生产者没有生产数据
                    lock.wait();//消费者等待
                }else {
                    System.out.println("消费者获得的值 "+ Data.value+"  当前线程的Name = "+Thread.currentThread().getName());
                    Data.value = " ";//模拟把数据消费了
                    lock.notify();//通知生产者赶快生产数据 ,我已经消费完了
                }
            }
        }
    }

    //生产者线程
    public static class ProThread implements Runnable{
        private Producer producer;
        public ProThread(Producer p){
            this.producer = p;
        }

        @Override
        public void run() {
            while (true){
                try {
                    producer.setValue();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //消费者线程

    public static class ConThread implements Runnable{
        private Consumer consumer;
        public ConThread(Consumer consumer){
            this.consumer = consumer;
        }
        @Override
        public void run() {
            try {
                while (true){
                    consumer.getValue();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws Exception{
        String lock = new String(" ");//使用同一个锁对象
        Thread p = new Thread(new ProThread(new Producer(lock)));
        Thread c = new Thread(new ConThread(new Consumer(lock)));
        p.setName("Producer");
        c.setName("Consumer");
        p.start();
        c.start();
    }
}

运行部分截图

这时一个生产者,一个消费者的情况,两个线程交替执行。

若果有多个消费者,多个生产者,则有可能产生“假死”现象,就是所有的线程都处于waitting,因为notify()方法一次只能使一个处于waitting状态的线程掉起来。解决办法使用notifiyAll()方法即可。

三,join():等待线程对象销毁,一个主线程要等待子线程结束在自行结束。

1,join()内部其实使用的是wait(),

 public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

join()方法具有使线程排队执行的作用,类似与同步的效果,但和synchroized的原理不同,后者使用 “对象监视器”原理

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章