画布 1
并发编程线程基础
  基本概念
    线程
      线程是进程的一个实体，一个进程中至少有一个线程
      同一个进程中的多个线程共享进程的资源。
        多个线程共享进程的堆和方法区资源
        每个线程有自己的程序计数器和栈区域
      CPU将资源分配给线程，因为真正要占用CPU运行的是线程，线程是CPU分配的基本单位
      程序计数器
        每个线程私有
        用于记录线程在让出CPU时的执行地址的，以便再次分配到时间片线程可以继续上次的地方执行
      栈区域
        每个线程私有
        用于存储该线程的局部变量，除此之外还用来存放线程的调用栈帧
    进程
      是代码在数据集合上的一次运行活动，是资源分配和调度的基本单位。
        操作系统分配资源是把资源分配给进程的，但是CPU资源是被分到线程上的
      堆
        主要存放new出来的对象实例
          进程内的所有线程共享
      方法区
        存放JVM加载的类、常量以及静态变量等信息
          进程内的所有线程共享
    并行
      是指两个或者多个事件在同一时刻发生
        强调的是同时
    并发
      是指两个或者多个事件在同一时间段发生
        强调的是一个时间段
  线程的创建与运行
    继承Thread接口
      缺点
        不能再继承其他的类
        任务和线程未分离，当多个线程执行同一个任务时有重复的代码
      优点
        获取当前线程直接使用this即可（很勉强的一个优点）
        方便传参，你可以在子类里面添加成员变量，通过 set 方法设置参数或者通过构造函数进行传递
    实现接口
      实现Runnable接口
        优点
          实现了接口run方法，指定了每个线程要执行的任务，是一个一个的任务
          降低了线程对象和线程任务的耦合性
          避免了继承Thread类的单继承的局限性
        缺点
          没有返回值
          只能使用主线程里面被声明为 final 的变量
      实现Callable接口（FutureTask配合使用）
        实现Callable接口的call()方法，以Callable接口实例创建FutrueTask对象，用该对象作为任务创建一个线程并启动它。
        集成Runnable的优点并且有返回值
        只能使用主线程里面被声明为 final 变量
  Java中的六种线程状态
    初始（NEW）
      新创建了一个线程对象，但是还没有调用start()方法。
    运行（RUNNABLE）
      Java线程种将就绪（Ready）和运行中（Running）两种状态统称为“运行”。
    阻塞（BLOCKED）
      标识线程阻塞于锁
    等待（WAITING）
      进入该状态的线程需要等待其他线程做出一些特定动作（通知或中断）。
    超时等待（TIMED_WAITING）
      该状态不同于WAITING，它可以在指定时间后自行返回。
    终止（TERMINATED）
      标识该线程已经执行完毕
  多线程的同步控制
    wait()函数
      调用该共享变量的 wait() 方法的线程会被阻塞，直到被其他线程唤醒，或者打断。
      调用该方法前的线程必须先获得该共享变量的监视器锁，调用后当前线程会将锁（只释放当前共享对象的锁，其他锁并不会释放）释放并进入阻塞状态。
      如果没有获得该对象的监视器锁，调用 wait() 方法会抛出 IllegalMonitorStateException 异常。
        注意：只能在获得锁的情况下调用
      虚假唤醒问题
        一个线程在没有被其他线程调用 notify()、notifyall() 方法进行通知，或者被中断，或者等
待超时，由挂起状态变为可运行状态。
          解决方法就是不停的去循环判断是否满足唤醒条件
            while(条件不满足){obj.wait()} 不满足条件就一直循环调用wait()防止虚假唤醒
      底层就是调用wait(0)
    wait(long timeout)函数
      在指定时间内未被唤醒，会抛出 IllegalArgum entException 异常
    wait(long timeout, int nanos)函数
      其内部调用的是 wait(long timeout) 函数，只有在 nanos > 0 时才使参数 timeout 递增 1
    notify()函数
      会唤醒一个在该共享变量上调用 wait 系列
方法后被挂起的线程（随机一个，只有一个）。
        被唤醒的线程也需要等待获得锁后（与其他线程一起竞争），才能从原来的 wait() 方法位置继续执行。
      只有获取到该对象的锁后才能调用，否则会抛出IllegalMonitorStateException 异常
    notifyall()函数
      会唤醒在该共享变量上调用 wait 系列
方法后被挂起的所有线程
      与notify一样需要获得对象的锁才能使用
    join()函数
      调用该方法的线程进入阻塞状态，等待目标线程执行完毕后，再往下执行；
        注意：是调用此方法的线程阻塞
    sleep()函数
      调用线程暂时让出指定时间的执行权（也就是这期间不参与CPU的调度）
        注意：该方法不会释放锁
      待指定时间过去后线程就会进入就绪状态，然后参与CPU调度。
      Thread类静态方法
    yield()函数
      调用此方法的线程让出时间片，再度进入Ready状态，重新竞争CPU时间片。
        调用该方法的线程不一定会停止执行，只是再次参与竞争。
          注意：该方法并不会释放锁
  上下文切换
    程序计数器
    上下文
      保存线程在让出CPU时当前环境的执行现场（环境），当再次执行时根据保存的执行现场信息恢复执行现场。
    切换时机
      当前线程的 CPU 间片使用完处于就绪状态时
      当前线程被其他线程中断时
      当线程调用wait系列函数，sleep方法、yield方法时
  线程中断
    interrupt()
      中断线程，为目标线程设置中断标志，实际并没有被中断，他会继续往下执行。
      如果目标线程因为调用了 wait 系列函数、 join 方法或者 sleep 方法而被阻塞挂起，这时其他线程调用目标线程该方法，目标线程在会调用该方法的地方抛出 InterruptedExcption 异常并返回。
    isInterrupted()
      检测当前线程是否被中断（中断标志），如果是返回 true，否则返回 false
      可以配合中断标志完成一些操作，比如优雅的退出线程
    interrupted()
      Thread类的静态方法
      检测当前线程是否被中断，如果是返回 true，否则返回 false
        注意：获取的当前调用线程的中断标志而不是调用interrupted()方法实例对象的中断标志。
      如果当线程被中断（中断标志为true），则会清除中断标志
  线程死锁
    死锁是指两个或两个以上的线程在执行过程中，因争夺资源而造成的互相等待的现象
    死锁产生条件
      互斥条件
        指线程对己经获取到的资源进行排它性使用，即该资源同时只由一个线程占用。如果此时其他线程请求该资源，请求者只能等待，直至占有资源的线程释放该资源。
      请求并持有条件
        指一个线程己经持有了至少一个资源，但又提出了新的资源请求，而新资源已被其他线程占有，所以当前线程会被阻塞，但阻塞的同时并不释放自己以获得的资源。
      不可剥夺条件
        指线程获取到的资源在自己使用完之前不能被其他线程抢占，只有自己使用完毕后才由自己释放该资源。
      环路等待条件
        指在发生死锁时，必然存在一个线程--资源的环形链，即线程集合{T0、T1、T2、...、Tn}中的 T0 正在等待 T1 占用的资源，T1 正在等待T2占用的资源，以此类推。
    如何避免死锁
      资源申请的有序性原则
        假如线程A和线程B都需要资源 1, 2, 3, .. . , n时，对资源进行排序，线程A和线程B只有在获取了资源 n-1 时才能去获取资源 n。
          资源的有序性破坏了资源的请求并持有条件和环路等待条件，因此避免了死锁
  守护线程与用户线程
    用户线程（user）
      用户线程还存在时JVM并不会退出终止
    守护线程（daemon）
      当没有用户线程还在执行时，即便守护线程还在执行中，JVM依然会退出终止。
  ThreadLocal
    详情查看我的笔记：https://devildyw.github.io/2022/02/28/ThreadLocal/