Skip to content

Latest commit

 

History

History
45 lines (36 loc) · 2.62 KB

ThreadMsg.md

File metadata and controls

45 lines (36 loc) · 2.62 KB

Java 线程间有多少通信方式?

通信方式

  • ①同步
  • ②while轮询的方式
  • ③wait/notify机制
  • ④管道通信

一. 同步

  • 多个线程通过synchronized关键字这种方式来实现线程间的通信。
  • 本质上就是“共享内存”式的通信。多个线程需要访问同一个共享变量,谁拿到了锁(获得了访问权限),谁就可以执行。
例如:

线程A和线程B持有同一个MyObject类的对象object,尽管这两个线程需要调用不同的方法,但是它们是同步执行的,比如:线程B需要等待线程A执行完了methodA()方法之后,它才能执行methodB()方法。这样,线程A和线程B就实现了 通信。

二. while轮询的方式

  • 线程A不断地改变条件,线程ThreadB不停地通过while语句检测while中的条件是否成立 ,从而实现了线程间的通信。
缺点:
- 1. 会浪费CPU资源。因为JVM调度器将CPU交给线程B执行时,它一直在轮询。
- 2. 轮询的条件的可见性问题:线程都是先把变量读取到本地线程栈空间,然后再去再去修改的本地变量。因此,如果线程B每次都在取本地的 条件变量,那么尽管另外一个线程已经改变了轮询的条件,它也察觉不到,这样也会造成死循环。

三. wait/notify机制

  • 通过Object类的 wait() 和 notify() 方法完成两个线程间的通信。
  • 当条件未满足时,线程A调用wait() 放弃CPU,并进入阻塞状态。
  • 当条件满足时,线程B调用 notify()通知 线程A,所谓通知线程A,就是唤醒线程A,并让它进入可运行状态。
优点:
  • CPU的利用率提高了。
缺点:
  • 如果通知过早,会打乱程序的执行逻辑。
    • 比如,线程B先执行,一下子添加了5个元素并调用了notify()发送了通知,
    • 而此时线程A还执行;
    • 当线程A执行并调用wait()时,那它永远就不可能被唤醒了。
    • 因为,线程B已经发了通知了,以后不再发通知了。这

四. 管道通信

  • 使用java.io.PipedInputStream 和 java.io.PipedOutputStream进行通信
类似共享内存机制和消息通信机制的区别
类共享内存机制:
  • ①中的synchronized关键字和②中的while轮询 “属于” 共享内存机制
  • 由于是轮询的条件使用了volatile关键字修饰时,这就表示它们通过判断这个“共享的条件变量“是否改变了,来实现进程间的交流。
类消息通信机制

管道通信,更像消息传递机制:通过管道,将一个线程中的消息发送给另一个。