《Java多线程编程核心技术》(三)

线程间的通信

主要技术点:

  • 使用wait/notify实现线程间的通信;
  • 生产者消费者模式的实现;
  • 方法join的使用
  • ThreadLocal的使用

等待/通知机制

方法wait()的作用是使当前代码执行的线程进行等待,该方法将当前线程置入“欲执行队列”中。
方法notify()的作用是进行通知,由线程规划器挑选wait()的线程进行执行。wait()方法和notify()方法都需要在同步块下执行,否则会抛异常。同步代码块执行到wait()方法时,会立即释放对该代码块的锁,进行等待状态,执行到notify()方法时,notify()会发出通知到其他wait()线程,但是notify()方法所在的同步块不会立即释放锁。

  • wait()方法:可以使调用该方法的线程释放共享资源的锁,然后从运行状态退出,进入等待状态,直到再次被唤醒;
  • notify()方法:可以随机唤醒等待队列中等待同一共享资源的“一个”线程,并使该线程推出等待队列,进入可运行状态,notify()方法仅通知一个线程;
  • notifyAll()方法:使所有正在等待队列中等待同意共享资源的“全部”线程从等待状态退出,进入可执行状态。

1)新创建一个新的线程对象后,在调用它的start()方法,系统会为此线程分配CPU资源,使其处于Runnable(可运行)状态,如果抢到CPU资源就进入Running(运行)状态;
2)Runnable状态和Running状态可以相互切换,线程进入Runnable状态大体分为以下五种情况:

  • 调用sleep()方法后经过的时间超过了指定的休眠时间;
  • 线程调用的阻塞IO已经返回,阻塞方法执行完毕;
  • 线程成功获得了试图同步的监视器;
  • 线程正在等待某个通知,其他线程发出了通知;
  • 处于挂起的线程调用了resume()恢复方法。

3)Blocked是阻塞的意思,阻塞状态结束后,线程进入Runnable状态,出现阻塞状态的情况:

  • 线程调用sleep()方法,主动放弃占用的处理器资源;
  • 线程调用了阻塞式IO方法,在该方法返回前,该线程被阻塞;
  • 线程试图获得一个同步监视器,但该同步监视器被其他线程占有;
  • 线程等待某个通知;
  • 线程调用了suspend()方法,被挂起。

4)run()方法运行结束进入销毁阶段,整个线程执行完毕。

方法wait(long):带一个参数的wait方法的功能是等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。

管道流(pipeStream):管道流是一种特殊的流,用于在不同线程间直接传送数据。一个线程发送数据到输出管道,其他线程从输入管道中读取数据,通过使用管道实现不同线程之间的通信。

join()方法的使用:

等待线程对象销毁。方法join的作用是使所属的线程对象x正确执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后在继续执行线程z后面的代码。
join(long)方法与wait(long)的区别:

  • join(long)执行完之后释放锁;
  • wait(long)执行完之后不释放锁。

类ThreadLocal的使用

类ThreadLocal主要解决的就是每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存储每个线程的私有数据。类ThreadLocal解决的是变量在不同线程之间的隔离性,也就是不同线程拥有自己的值,不同线程中的值是可以放入的ThreadLocal类中进行保存的。

扫描二维码关注公众号,回复: 8975326 查看本文章

类InheritedThreadLocal的使用

使用InherThreadLocal类可以在子线程中获取父线程继承下来的值。子线程可以对父线程的值进行更改,但是应当注意,如果子线程在取得值得同时,主线程将InheritedThreadLocal中得值进行更改,那么子线程取到的值还是旧值。

发布了12 篇原创文章 · 获赞 5 · 访问量 9956

猜你喜欢

转载自blog.csdn.net/weixin_44532540/article/details/103643906