Java 线程基础

目录

    • 一 线程状态
    • 二 线程中止
      • stop
      • interrupt
      • 标志位
    • 三 线程通信
      • JDK API
        • suspend/resume机制被弃用
        • wait/notify机制
        • park/unpark机制
      • 伪唤醒
    • 四 线程封闭
      • ThreadLocal
      • 栈封闭
    • 五 内存屏障和CPU缓存
    • 六 线程池
      • 线程池API-接口定义和实现
      • 线程池API-方法定义

一 线程状态

6个状态定义:java.lang.Thread.State

  1. New:尚未启动的线程的状态。
  2. Runnable:可运行线程的线程状态,等待CPU调度。
  3. Blocked:线程阻塞等待监视器锁定的线程状态。
    处于synchronized同步代码块或方法中被阻塞。
  4. Waiting:等待线程的线程状态。不带超时的方式:
    Object.wait、Thread.join、LockSupport.Park
  5. Timed Waiting:具有指定等待时间的等待线程的线程状态。带超时的方式:Thread.sleep、Object.wait、Thread.join、LockSupport.parkNanos、LockSupport.ParkUntil
  6. Terminated:终止线程的线程状态。线程正常完成执行或者出现异常。
Java 线程基础_第1张图片

二 线程中止

stop

强行中止线程,并且清楚监控器锁的信息,但是可能导致线程安全的问题,JDK不建议用。

interrupt

  1. 如果目标线程在调用Object class的wait()、wait(long)或wait(long,int)方法、join()、join(long,int)或sleep(long,int)方法时被阻塞,那么interrupt会生效,该线程的中断状态将被清除,抛出InterruptedExecption异常。
  2. 如果目标线程是被I/O或者NIO中的Channel所阻塞,同样,I/O操作会被中断或者返回特殊异常值。达到终止线程的目的。
  3. 如果以上条件都不满足,则会设置此线程的中断状态。

标志位

代码逻辑中增加一个判断用来控制线程的中止。

三 线程通信

要想实现多个线程之间的协同,如:线程执行的先后顺序、获取某个线程执行的结果等。涉及到线程之间相互通信,分为下面四类:

  1. 文件共享
  2. 网络共享
  3. 共享变量
  4. jdk提供的线程协调API
    细分为:suspend/resume、wait/notify、park/unpark

JDK API

JDK中对于需要多线程写作完成某一任务的场景,提供了对应API支持。、
多线程协作的典型场景是:生产者-消费者模型(线程阻塞、线程唤醒)。

suspend/resume机制被弃用

suspend挂起目标线程,resume恢复线程执行。
被弃用的主要原因是,容易写出死锁的代码。所以用wait/notify和park/unpark机制对它进行替代。

  1. suspend挂起之后并不会释放锁,故此容易写出死锁代码。
  2. 先执行suspend,再执行resume。反之死锁。

wait/notify机制

  • 这些方法只能由同一对象锁的持有者线程调用,也就是写在同步代码块里面,否则会抛出IlegalMonitorStateException异常。
  • wai方法导致当前线程等待,加入该对象的等待集合中,并且放弃当前持有的对象锁。notify/notifyAll方法唤醒一个或所有正在等待这个对象锁的进程。

注意:虽然wait会自动解锁,但是对顺序有要求,如果在notify被调用之后,才开始wait的调用,线程会永远处于WAITING状态。

park/unpark机制

  • 线程嗲用park则等待“许可”,unpark方法为指定线程提供“许可permit”。
    不要求park和unpark方法的调用顺序。
  • 多次调用unpark之后,再调用park,线程会直接运行,但不会叠加,也就是说,连续多次调用park方法,第一次会拿到“许可”直接运行,后续调用会进入等待。
  • 不是基于监视器锁实现,park不会释放锁。

伪唤醒

伪唤醒是指线程并非因为notify、notifyAll、unpark等api调用而唤醒,是更底层原因导致的。

  • 官方建议应该在循环中检查等待条件,原因是处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。

四 线程封闭

多线程访问共享可变数据时,涉及到线程间数据同步的问题。并不是所有时候都要用到共享数据,所以线程封闭概念就提出来了。

数据都被封闭在各自的线程之中,就不需要同步,这种通过将数据封闭在线程中而避免使用同步的技术称为线程封闭。

  • 线程封闭具体的体现有:ThreadLocal、局部变量。

ThreadLocal

ThreadLocal是Java里一种特殊变量。
它是一个线程级别变量,每个线程都有一个ThreadLocal就是每个线程拥有了自己独立的一个变量,竞争条件被彻底消除,在并发模式下是绝对安全的变量。

  • 用法:ThreadLocal var=new ThreadLocal();

会自动在每个线程上创建一个T的副本,副本之间彼此独立,互不影响。
可以用ThreadLocal存储一些参数,以便在线程的多个方法中使用,用来替代方法传参的做法。

可以理解为,JVM维护了一个Map,每个线程都要用这个T的时候,用当前的线程去Map里面取。仅作为一个概念理解。

栈封闭

局部变量的固有属性之一就是封闭在线程中,它们位于执行线程的栈中,其他线程无法访问这个栈。

五 内存屏障和CPU缓存

Java 线程基础_第2张图片
Java 线程基础_第3张图片
Java 线程基础_第4张图片
Java 线程基础_第5张图片
Java 线程基础_第6张图片
Java 线程基础_第7张图片

六 线程池

Java 线程基础_第8张图片
Java 线程基础_第9张图片

线程池API-接口定义和实现

Java 线程基础_第10张图片

线程池API-方法定义

Java 线程基础_第11张图片

相关demo

你可能感兴趣的:(并发编程,并发编程,多线程,java)