wait/notify/join

线程通信

1,共享内存

2,wait/notify ->  基于某一个条件来等待或者唤醒 ,从而进行通信  可以基于wait()方法构建生产者消费者模型

以上图示说明:1,两个线程必须抢占同一把锁  2,wait/notify 方法必须在synchronized方法里面

wait()方法阻塞 一定会释放锁  注意此处释放锁但是不一定代表同步代码块执行结束

notify() 不会释放锁

//以下代码通过Queue这一个共享数据结构 来进行生产者消费者通信 基于某一个条件的判断 以下例子就是基于队列的大小

public class ProducerConsumerDemo() {

    public static void main(String[] args) throws InterruptedException{

        Queue<String> str = new LinkedList<>();

        Producer pro = new Producer(str, 10);

        Consumer con = new Consumer(str, 10);

        new Thread(pro).start();

        //保证生产者先运行

        Thread.sleep(1000);

        new Thread(con).start();

    }

}

public class Producer implements Runnable{

    private Queue<String> bags;

    private int  maxSize;

    public Producer(Queue<String> bags, int maxSize) {

        this.bags = bags;

        this.maxSize = maxSize;

    }

    @Override

    public void run(

        while(true){

            synchronized(bags) { //基于共享队列抢占锁

                if(bags.isEmpty()) {

                    System.out.println("bags is null");

                    try{

                        bags.wait(); //注意此处阻塞释放锁但是不一定代表同步代码块执行结束,被唤醒之后,同步队列里面的线程抢占到锁以后才会继续执行被阻塞的地方下面的代码

                    }catch(InterruptedException e){

                        e.printStackTree();

                    }

                    try{

                        Thread.sleep(100);

                    }catch(InterruptedException e ){

                        e.printStackTree();

                    }

                    System.out.println("生产者生产数据 : bag" + i);

                    bags.add("bag"+i);

                    bags.notify() //

                }//此处同步代码块执行结束

            }

        }

    }

}

public class Consumer{

    private Queue<String> bags;

    private int  maxSize;

    public Consumer(Queue<String> bags, int maxSize) {

        this.bags = bags;

        this.maxSize = maxSize;

    }

    @Override

    public void run(

        int i =0;

        while(true){

            i++;

            synchronized(bags) { //基于共享队列抢占锁  进行通信  这就是基于某一个条件的判断

                if(bags.size()==maxSize) {

                    System.out/println("bags is full");

                    try{

                        bags.wait();

                    }catch(InterruptedException e){

                        e.printStackTree();

                    }

                }

            try{   

                Thread.sleep(100);

            }catch(InterruptedException e){

                e.printStackTree();

            }

            String bag = bags.remove();

            System.out.println("消费者消费数据:bag" +bag);

            bags.notify();

            }

        }

    }

}

 附图:wait /notify  原理

1,waitThread抢占锁成功,满足条件调用Object.wait()方法阻塞当前线程并释放锁 进入等待队列

2,NotifyThread 成功获得锁,满足条件调动Object.notify()方法唤醒处于阻塞的线程,将其从等待队列移动到同步队列进行锁的竞争

wait notify 的底层还是 LockSupport.park/unpark   LockSuport不是java的实现 java 调用的是native方法 底层还是C++

为什么wait() notify()要放在synchronized里面

他们是基于共享变量(数据结构)进行通信,要满足条件互斥;等待唤醒都要对共享队列进行处理,synchronized可以达到这个目的

基于线程通信的原理应用  :除了wait notify  还有 join ,当调用join()方法线程的方法执行结束以后,给一个信号调用notity()方法,其实join方法里面也是调用了wait方法 

public class JoinDemo{

    private static int x=10;

    @Overide

    public void run() {

        try{

            x = 100;

        }catch(InterruptedException e){

            e.printStackTree();

        }

        //当run()方法执行结束,会给一个notify()信号

        //lock.notify_all()  查看hotspot 源码

    }

     

    public static void main(){

        JoinDemo join = new JoinDemo();

        join.start();

        //wait()

        join.join(); //等待join线程执行结束| 如果没有执行结束则阻塞main线程

        if(x == 100) {

            System.out.println("main线程执行结束");

        }

    }

}

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;

        }

    }

}

 但是代码里面并没有看到notify的影子,因为这块实现是在jvm里面实现的,线程结束以后会调用释放join的方法,其实就是调用lock.notify

java --jvm --os  thread.cpp

static void ensure_join(JavaThread* thread) {

        // We do not need to grap the Threads_lock, since we are operating on ourself.

    Handle threadObj(thread, thread->threadObj());

    assert(threadObj.not_null(), "java thread object must exist");

    ObjectLocker lock(threadObj, thread);

        // Ignore pending exception (ThreadDeath), since we are exiting anyway

    thread->clear_pending_exception();

        // Thread is exiting. So set thread_status field in java.lang.Thread class to

    TERMINATED.

    java_lang_Thread::set_thread_status(threadObj(),

    java_lang_Thread::TERMINATED);

        // Clear the native thread instance - this makes isAlive return false and

    allows the join()

        // to complete once we've done the notify_all below

    java_lang_Thread::set_thread(threadObj(), NULL);

    lock.notify_all(thread);

        // Ignore pending exception (ThreadDeath), since we are exiting anyway

    thread->clear_pending_exception();

}

基于上面的分析理解,下面会继续分析j.u.c  中Condition源码 CSDNicon-default.png?t=L892https://mp.csdn.net/mp_blog/creation/editor/120616974

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tudou186

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值