Java并发编程基础

线程的状态

线程的状态

线程的状态变化

线程的状态变化

Daemon 线程

  • Daemon 线程是一种支持型线程(常被叫做守护线程),因为它主要被用作程序中后台调度以及支持性工作。
  • 可以通过调用 Thread.setDaemon(true) 将线程设置为 Daemon 线程。

中断

  • 许多声明抛出 InterruptedException 的方法(例如 Thread.sleep(long millis) 方法)在抛出 InterruptedException 之前,Java 虚拟机会先将该线程的中断标识位清除,然后抛出 InterruptedException。此时调用 isInterrupted() 方法将会返回 false

安全地终止线程

  • 使用标志位
  • 使用中断

线程间通信

  • volatile 和 synchronized 关键字
  • 等待/通知机制
    • 难以确保及时性
    • 难以降低开销
    • 等待/通知的相关方法是任意 Java 对象都具备的,因为这些方法被定义在所有对象的超类 java.lang.Object 上。
    • 等待/通知机制
    • 不同线程之间通过锁对象的 waitnotify 方法进行消息传输。

细节问题

  • 使用 wait()notify()notifyAll() 时需要先对调用对象加锁。
  • 调用 wait() 方法后,线程状态由 RUNNING 变为 WAITING,并将当前线程放置到对象的等待队列。
  • notify()notifyAll() 方法调用后,等待线程依旧不会从 wait() 返回,需要调用 notify()notifyAll() 的线程释放锁之后,等待线程才有机会从 wait() 返回。
  • notify() 方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而 notifyAll() 方法则是将等待队列中所有的线程全部移到同步队列,**被移动的线程状态由 WAITING 变为 BLOCKED**。
  • wait() 方法返回的前提是获得了调用对象的锁。

管道输入/输出流

  • PipedOutputStreamPipedInputStreamPipedReaderPipedWriter,前两种面向字节,而后两种面向字符。
  • 对于 Piped 类型的流,必须先进行绑定,也就是调用 connect() 方法,如果没有将输入/输出流绑定起来,对于该流的访问将会抛出异常。

Thread.join() 的使用

  • 如果一个线程 A 执行了 thread.join() 语句,其含义是:当前线程 A 等待 thread 线程终止之后才从 thread.join() 返回。

ThreadLocal 的使用

  • ThreadLocal,即线程变量,是一个ThreadLocal 对象为键、任意对象为值的存储结构。这个结构被附带在线程上,也就是说一个线程可以根据一个 ThreadLocal 对象查询到绑定在这个线程上的一个值
  • 可以通过 set(T) 方法来设置一个值,在当前线程下再通过 get() 方法获取到原先设置的值。

线程应用实例

  • 等待超时模式

Java线程六种状态及切换

  • 刚刚创建了 Thread,但是没有调用 start 方法的时候,线程处于 NEW 状态
  • 调用 start 方法后,线程会进入 RUNNABLE 状态
    • 多次调用一个线程的 start 方法会怎么样?
      • 线程内部有一个 threadStatus 变量,在刚创建的 new 状态的时候,该变量值为 0,在运行后,或者切换线程状态后,该 threadStatus 会改变,这会导致线程在第二次调用 start 方法的时候抛出异常
    • 一个线程执行完毕,处于 TERMINATED 状态,再次调用这个线程的 start 方法是否可行?
      • 不可,处于 TERMINATED 状态的线程的 threadStatus2

RUNNABLE 状态

  • 表示当前线程正在运行中。处于 RUNNABLE 状态的线程在 Java 虚拟机中运行,也有可能在等待 CPU 分配资源。Java 线程的 RUNNABLE 状态其实包括了操作系统线程的 ready 和 running 两个状态。

BLOCKED 状态

  • 处于 BLOCKED 状态的线程正在等待锁的释放以进入同步区。

WAITING 状态

  • 等待状态。处于等待状态的线程变成 RUNNABLE 状态需要其他线程唤醒。
  • 调用下面这 3 个方法会使线程进入等待状态:
    • Object.wait()
    • Thread.join()
    • LockSupport.park()

TIMED_WAITING 状态

  • 超时等待状态。线程等待一个具体的时间,时间到后会被自动唤醒。
  • 调用如下方法会使线程进入超时等待状态:
    • Thread.sleep()
    • Object.wait()
    • Thread.join()
    • LockSupport.parkNanos(long nanos)
    • LockSupport.parkUntil(long deadline)

调用 wait() 方法前,线程必须持有对象的锁。