线程通信
1,共享内存
2,wait/notify -> 基于某一个条件来等待或者唤醒 ,从而进行通信 可以基于wait()方法构建生产者消费者模型
![](https://img-blog.csdnimg.cn/20211005134738140.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAdHVkb3UxODY=,size_20,color_FFFFFF,t_70,g_se,x_16)
以上图示说明: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 原理
![](https://img-blog.csdnimg.cn/20211005134747372.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAdHVkb3UxODY=,size_20,color_FFFFFF,t_70,g_se,x_16)
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源码 CSDN
https://mp.csdn.net/mp_blog/creation/editor/120616974