Java多线程编程核心技术--第三章

Chapter 3

使用线程间通信,会增强系统间的交互性,提高 CPU 的利用率。
这章的核心内容如下:
- 使用 wait()/notify() 实现线程之间通信
- 生产者/消费者模式的实现
- join() 方法的使用
- ThreadLocal 类的使用

1

  • 不使用 wait()/notify() 如何实现线程之间通信?

    创建2个线程,2个线程中放入同一对象,A中遍历添加元素到集合中,B中用while来执行死循环获取当集合长度为多少时抛出异常。这是简单的一个案例。

  • 等待/通知机制实现

    通过 wait()/notify() 。他们都是 Object 类的方法。

    1. wait()

      • 使线程停止运行
      • 只能在同步方法或者同步代码快中执行
      • wait() 执行后,释放当前对象锁。执行前没有合适锁对象,会抛出异常。
    2. notify()
      • 使停止的线程继续运行
      • 只能在同步方法或者同步代码快中执行
      • 执行前没有合适锁对象,会抛出异常,执行后,只有退出了synchronized方法后才会释放当前对象锁。
    3. 当线程数很多的时候,用notifyAll()唤醒所有线程
    4. wait(long) 在某个时间内是否有线程对其唤醒,否则超时自动唤醒.
    5. 如果通知过早,会影响逻辑性(但是线程启动不是有随机性嘛,小概率事件会正常,不过我运行很多次都是影响的,囧)

      • 等待/通知机制的经典案例–生产者/消费者模式
    6. 多生产者-多消费者:假死

    原因:有可能notify()唤醒的是同类,积少成多,造成假死

    解决:将异类一起唤醒即可,使用notifyAll()

    1. 解决wait()条件改变与假死

    原因:多个线程在wait后重新执行时,后面的操作异常导致。
    解决:使用while

    扫描二维码关注公众号,回复: 1531913 查看本文章
  • 通过管道实现进程间通信

    • pipeSteam:同于在不同线程间直接传送数据。
      1. 字节流-PipedInputStream/PipedOutputStream
      2. 字符流-PipedReader/PipedWriter

2

  • join() 等待线程对象的销毁

    场景:当需求是要在子线程操作一个数据,主线程需要获取这个值。
    特点:底层是 wait() 实现,会释放锁。

  • 情况一

    join(long) 后面的代码提前运行,why?

    设置等待时间超时,释放锁,执行后面的代码

3

  • ThreadLocal – 让每个线程绑定自己的值

    • 原因:变量值的共享可以用public static ,所有线程都共享同一个static变量,每个线程如果要实现自己的共享变量呢?
    • 解决:ThreadLocal 让每个线程都有自己的共享变量。就像一个全局存放数据的盒子,盒子中存储每个线程的私有数据。
    • initialValue 设置初始值
    • set()/get() 设置/获取值
  • InheritableThreadLocal – 使子线程从父线程中取值

    • 主线程和子线程的区别

    UI界面和Main函数均为主线程。
    被Thread包含的“方法体”或者“委托”均为子线程。

    • 子线程取到值的同时,主线程更改值,那么会取到旧值

猜你喜欢

转载自blog.csdn.net/ouzhuangzhuang/article/details/80607836