Skip to content

https://pdai.tech/md/java/thread/java-thread-x-thread-basic.html

  1. 线程有哪几种状态? 分别说明从一种状态到另一种状态转变有哪些方式?
  2. 通常线程有哪几种使用方式?
  3. 基础线程机制有哪些?
  4. 线程的中断方式有哪些?
  5. 线程的互斥同步方式有哪些? 如何比较和选择?
  6. 线程之间有哪些协作方式?

线程的状态

线程有六种状态

  1. 新建(NEW):创建后尚未启动。
  2. 可运行(Runable):可运行状态,但是可能还没有运行,在等待CPU时间片
  3. 阻塞(Blocking):等待获取一个排它锁,如果其线程释放了锁就会结束此状态
  4. 无限期等待(Waiting):等待其它线程显式地唤醒,否则不会被分配 CPU 时间片。
  5. 限期等待(Timed Waiting):无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒。
  6. 死亡(Terminated):可以是线程结束任务之后自己结束,或者产生了异常而结束。

阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁。而等待是主动的,通过调用 Thread.sleep() 和 Object.wait() 等方法进入。

状态转换

image.png

创建线程

实现Runable接口

  1. 定义一个类实现Runable接口和run方法
  2. 创建Runable接口实现类的对象
  3. 将此Runable接口实现类的对象作为传递到Thread构造器中,创建Thread的对象。
  4. 通过Thread对象调用start方法启动
java
public class MyRunnable implements Runnable {
    public void run() {
        // ...
    }
}
java
public static void main(String[] args) {
    MyRunnable instance = new MyRunnable();
    Thread thread = new Thread(instance);
    thread.start();
}

继承Thread类

  1. 继承Thread类并实现run方法
  2. 调用start启动
java
//1.继承Thread类并实现run方法
public class MyThread extends Thread {
    public void run() {
        // ...
    }
}

//2.调用start方法启动
public static void main(String[] args) {
    MyThread mt = new MyThread();
    mt.start();
}

实现Callable接口

Callable 可以有返回值,返回值通过 FutureTask 进行封装。

  1. 创建一个类继承Callable接口,实现call方法
  2. 创建Callable接口实现类的对象。
  3. 将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象。
  4. 将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()方法。
java
public class MyCallable implements Callable<Integer> {
    public Integer call() {
        return 123;
    }
}


public static void main(String[] args) throws ExecutionException, InterruptedException {
    MyCallable mc = new MyCallable();
    FutureTask<Integer> ft = new FutureTask<>(mc);
    Thread thread = new Thread(ft);
    thread.start();
    System.out.println(ft.get());
}

线程安全互斥同步

回顾以下上一篇笔记中记录的保证线程安全的机制:Java多线程理论基础

  1. 互斥同步: synchronizedReentrantLock
  2. 非阻塞同步: CAS, AtomicXXXX
  3. 无同步方案: 栈封闭,Thread Local,可重入代码

这里主要讲解Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问

  1. JVM 实现的 synchronized(同步锁)
  2. JDK 实现的 ReentrantLock

synchronized

Java多线程之详解synchronized关键字 作用对象可以是代码块、方法、类 作用于代码块和方法时,获得的是对象锁,不同的线程通过同一个对象去调用加锁的代码块和方法时,线程会同步。不同的线程通过不同的对象去调用加锁的代码块和方法时,线程不会同步 作用于类时,获得的是类锁,作用于整个类上。也就是说两个线程调用同一个类的不同对象上的这种同步语句,也会进行同步。(作用于静态方法也是获得类锁)

ReentrantLock

ReentrantLock 是 java.util.concurrent(J.U.C)包中的锁。