Featured image of post 精读《Java并发编程的艺术》(一)

精读《Java并发编程的艺术》(一)

从零开始精读《Java并发编程的艺术》第一章,并发编程初探

并发编程初探

Java天生的多线程

当前的main函数就是一个JVM进程,在IDEA中可以看到共有6条线程

查看线程信息:jps(拿到线程的tid) + jstack(查看线程日志)

prio是进程中的优先级,os_prio是操作系统给线程定义的优先级,prio前加上deamo则为守护线程

截图

  • [6] Monitor Ctrl-Break (跟JVM 关系不大,他是 IDEA 通过反射的方式,开启一个随着我们运行的jvm进程开启与关闭的一个监听线程。)

    daemon prio=5 (可延迟开启)

  • **[5] Attach Listener **(附加监听器。 简单来说,他是jdk里边一个工具类提供的jvm 进程之间通信的工具。 cmd – java -version; jvm – jstack、jmap、dump) 进程间的通信。

    daemon prio=5 (可延迟开启)

    开启我们这个线程的两个方式: 1. 通过jvm参数开启。-XX: StartAttachListener延迟开启: cmd – java -version –> JVM 适时开启A L 线程

  • [4] Signal Dispatcher (信号分发器。 我们通过cmd 发送jstack,传到了jvm进程,这时候信号分发器就要发挥作用了。)

    daemon prio=9

  • [3] Finalizer JVM 垃圾回收相关的内容。

    1. daemon prio=10 高优先级的守护线程。
    2. 只有当开始一轮垃圾收集的时候,才会开始调用finalize方法。
    3. jvm在垃圾收集的时候,会将失去引用的对象封装到我们的 Fianlizer 对象(Reference), 放入我们的 F-queue 队列中。由 Finalizer 线程执行inalize方法
    4. Finalizer 专注垃圾收集,垃圾收集 – 并行收集,不阻碍用户线程,低优先级线程。 prio=8 他是一个守护线程啊。而且这个线程目前并没有真正的开启,不足以发生minorgc或者是 full gc
  • [2] Reference Handler (引用处理的线程。强,软,弱,虚。 -GC 有不同表现 - JVM深入分析)

    引用处理线程-GC相关线程

    daemon prio=10(GC很重要,优先级较高)

  • [1] main 主线程

    prio=5

    操作系统面向的是JVM 进程,JVM 进程里面向的是 我们的main函数,。所以对于我们的操作系统如何看待我们的main函数优先级,无所谓。 只要os 给我们jvm进程足够公平的优先级就行。

线程的状态

截图

注:上图的 Obejct.join() 应为 Thread.join()

Thread.Sleep() 和 Object.Wait()

Thread.Sleep()

  • 不释放锁
  • 响应中断(对中断敏感)
  • 会释放CPU

Obeject.wait()

  • 会释放锁
  • 响应中断(对中断敏感)
  • 会释放CPU,让出时间片并进入等待队列

注:wait(0)表示永久等待

Thread.join()

底层调用Object.Wait()

  • 会释放锁

    • Thread的join方法,释放的是当前调用 join方法的那个对象的锁。

    • 1
      2
      3
      4
      5
      6
      
      synchronized (obj){
        thread.join();//不释放锁
      }
      synchronized (Thread.currentThread){
        thread.join();//释放锁
      }
      
  • 响应中断(对中断敏感)

线程间的通讯方式

  1. volitate 、synchronize、lock。(都保证可见性)

  2. wait、notify、await() 、 signal

  3. 管道输入、输出流**(已过时)**

    管道输入/输出流和普通的文件输入/输出流或者网络输入/输出流不同之处在于,它主要用于线程之间的数据传输,而传输的媒介为内存。管道输入/输出流主要包括了如下4种具体实现:PipedOutputStream、PipedInputStream、PipedReader和PipedWriter,前两种面向字节,而后两种面向字符。

  4. Thread.join() : 隐式唤醒。等待其他线程执行完成,其他线程会发送唤醒信号。

  5. ThradLocal():支持子线程集成的一种形式。

  6. 线程中断

    线程中断时,sleep()会先清理中断标记,再抛出异常,导致thread.interupted = flase

Built with Hugo
主题 StackJimmy 设计