ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

《Java多线程编程核心技术第二版》读书笔记

2021-11-19 22:31:43  阅读:156  来源: 互联网

标签:Java Thread thread 读书笔记 ThreadLocal 线程 child 多线程 方法


一、总结

这本书写的很浅,更多的是案例,ThreadLocal部分还可以,原理基本讲到了

大致总结了下面部分知识点

二、内容

在什么情况下使用多线程?

  • 阻塞
  • 依赖,如业务分为两个执行过程,当A业务阻塞的时候,B业务的执行不依赖A业务的执行结果

start()方法耗时的原因是因为执行了多个步骤

  • 通过JVM告诉操作系统创建Thread
  • 通过系统开辟内存并使用WindowsSDK中的createThread()函数创建Thread对象
  • 操作系统对Thread对象进行调度,以确定执行时机
  • Thread在操作系统内部成功执行

使用常见的命令分析线程

  • jps + jstack.exe:jps查看全部线程,然后jps -l 进程id
  • jmc.exe可视化界面
  • jvisualvm.exe可视化界面

停止一个线程

  • 使用退出标志正常退出
  • 使用stop()方法强制终止线程,同方法suspend()、remuse()都是过时的方法,使用可能发生不可意料的结果,因为过程不会释放锁
  • 使用interrupt()方法中断线程
  • yield()方法是暂停当前线程放弃cpu资源,但是放弃的时间不确定

优先级

  • 在Java中,线程的优先级1~10共10个等级
  • 线程优先级具有继承性,A线程创建B线程,他们的优先级相同

守护线程,Java中有两种线程

  • 非守护线程:即用户线程
  • 守护线程:当非守护线程不存在之后,自动销毁,典型的就是垃圾回收线程

同步关键字sychronized概述,使用javap命令反编译class文件为字节码

  • 方法加了synchronized,发现在方法前面多了ACC_SYNCHRONIZED
  • 同步代码块,使用monitorenter、monitorexit指令进行同步处理

注意

  • 加在非静态方法,对象锁锁的是当前类的Object实例对象,锁的并不是当前方法或者代码块的代码,而是第一个持有该方法的线程
  • 如果在X对象中使用了synchronized修饰非静态方法,则X对象就被当成锁
  • 可重入的,在synchronized修饰的代码块、方法内部调用本类的其他synchronized是永远可以拿到锁的
  • 加在静态方法,锁的是当前类的Class类对象,对所有的对象实例起作用

volatile三个特性

  • 可见性
  • 不保证原子性:加了volatile的变量执行i++也不是原子操作,需要配合synchronized
  • 禁止代码重排序

线程间通信

  • 执行noty()方法不会立即释放锁,执行wait()会立即释放锁,唤醒的顺序与wait的顺序一致,在生产者消费者模式不保证唤醒的是同类还是异类
  • xxx线程实例.join()方法执行,停止当前实例所在线程的执行,执行线程实例的run方法,有线程排队运行的结果
  • wait()方法释放锁,sleep()不释放锁

ThreadLocal类

  • 主要作用是将数据放到当前运行线程的成员变量Map中,本身不存储数据,作为桥梁
  • Map中的key存储的是ThreadLocal对象
  • Thread类内有一个内部内ThreadLocalMap,对应创建成员属性threadLocals,使用set的时候,会调用createMap()方法,该方法的实现在ThreadLocal类中
  • 初始调用ThreadLocal的实例对象的get()方法返回为null,可以继承ThreadLocal重写initialValue()方法设置初始值
  • ThreadLocal类不能实现值继承,创建子线程的父线程不会把设置的值传给子线程,可以使用InheritableThreadLocal体现值的继承性,它继承Thread类

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

InheriatbleThreadLocal实现值继承的原理

  • inheritableThreadLocals同threadLocals都是Thread的成员变量,开始为null
  • InheriatbleThreadLocal继承ThreadLocal但是没有方法上面无@Override
  • 调用InheriatbleThreadLocal对象的set()方法其实就是调用threadLocals的方法,因为没有重写set方法,而get()方法内部又调用的createMap()和getMap都是自己重写的方法

具体的原理就是:

  • 父线程调用InheriatbleThreadLocal实例的set()方法,就是向InheriatbleThreadLocal容器存数据
  • 进而在创建子线程的时候,子类主动引用其父线程的InheriatbleThreadLocal值


package java.lang;
import java.lang.ref.*;

/**
 * This class extends {@code ThreadLocal} to provide inheritance of values
 * from parent thread to child thread: when a child thread is created, the
 * child receives initial values for all inheritable thread-local variables
 * for which the parent has values.  Normally the child's values will be
 * identical to the parent's; however, the child's value can be made an
 * arbitrary function of the parent's by overriding the {@code childValue}
 * method in this class.
 *
 * <p>Inheritable thread-local variables are used in preference to
 * ordinary thread-local variables when the per-thread-attribute being
 * maintained in the variable (e.g., User ID, Transaction ID) must be
 * automatically transmitted to any child threads that are created.
 *
 * <p>Note: During the creation of a new {@link
 * Thread#Thread(ThreadGroup,Runnable,String,long,boolean) thread}, it is
 * possible to <i>opt out</i> of receiving initial values for inheritable
 * thread-local variables.
 *
 * @author  Josh Bloch and Doug Lea
 * @see     ThreadLocal
 * @since   1.2
 */

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
    /**
     * Computes the child's initial value for this inheritable thread-local
     * variable as a function of the parent's value at the time the child
     * thread is created.  This method is called from within the parent
     * thread before the child is started.
     * <p>
     * This method merely returns its input argument, and should be overridden
     * if a different behavior is desired.
     *
     * @param parentValue the parent thread's value
     * @return the child thread's initial value
     */
    protected T childValue(T parentValue) {
        return parentValue;
    }

    /**
     * Get the map associated with a ThreadLocal.
     *
     * @param t the current thread
     */
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }

    /**
     * Create the map associated with a ThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the table.
     */
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }
}

在这里插入图片描述
在这里插入图片描述

  • 子线程将父线程的table对象以赋值的方式赋值给子线程,这个过程是创建Thread对象的时候自动完成的,只要父线程的InheriatbleThreadLocal不为null
  • 父线程更新了InheriatbleThreadLocal的数据之后,子线程也不会更新,反之子线程更新也不影响父线程,但是指针指向的如一个对象的属性值,还是会变得。另外就是可以重写childValue()可以进行子线程对父线程继承的值进行加工

Lock对象的使用

  • JDK1.5新增的ReentrantLock类功能更多了,如嗅探锁定,多路分支等
  • 进程间通信需要借助Condition类的await()、signal()

标签:Java,Thread,thread,读书笔记,ThreadLocal,线程,child,多线程,方法
来源: https://blog.csdn.net/qq_24654501/article/details/121429650

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有