目录

1.LockSupport.park():休眠当前线程

2.LockSupport.unpark(线程对象):唤醒某一个指定的线程

3.扩展:LockSupport.parkUntil(long)等待最大时间是一个固定时间

4.LockSupport和Interrupt

5.LockSupport VS wait

相同点:

①二者都能使线程进入休眠状态。

②二者在不传递参数的情况下,都会让线程进入WAITING无限期等待状态。

不同点:

①LockSupport使用时不需要加锁,不需要配合synchronized一起使用;而wait需要配合synchronized一起使用。

②LockSupport不会抛出Interrupt的异常,而wait会。

③LockSupport可以指定某一个线程进行唤醒,而wait和notify不行。

PS:线程休眠4种方式:


有wait和notify是因为sleep只能到点之后再被唤醒,不能主动唤醒。

上述方法的问题:在调用notify时会随机唤醒,无法唤醒指定的某一个线程,不能把握线程唤醒的顺序。

使⽤ LockSupport 也可以使线程休眠和唤醒,它包含两个主要的⽅法↓

注:LockSupport 无需配合 synchronized 使用。

1.LockSupport.park():休眠当前线程

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程1:开始执行");
            LockSupport.park();
            System.out.println("线程1:结束执行");
        },"线程1");
        t1.start();
    }
}

java线程如何被唤醒 java 唤醒指定线程_加锁

java线程如何被唤醒 java 唤醒指定线程_java线程如何被唤醒_02

2.LockSupport.unpark(线程对象):唤醒某一个指定的线程

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程1:开始执行");
            LockSupport.park();
            System.out.println("线程1:结束执行");
        },"线程1");

        Thread t2 = new Thread(() -> {
            System.out.println("线程2:开始执行");
            LockSupport.park();
            System.out.println("线程2:结束执行");
        },"线程2");

        Thread t3 = new Thread(() -> {
            System.out.println("线程3:开始执行");
            LockSupport.park();
            System.out.println("线程3:结束执行");
        },"线程3");

        t1.start();
        t2.start();
        t3.start();

        Thread.sleep(1000);
        System.out.println();
        LockSupport.unpark(t1); //唤醒线程1开始执行

        Thread.sleep(1000);
        LockSupport.unpark(t2); //唤醒线程2开始执行

        Thread.sleep(1000);
        LockSupport.unpark(t3); //唤醒线程3开始执行
    }
}

java线程如何被唤醒 java 唤醒指定线程_java线程如何被唤醒_03

3.扩展:LockSupport.parkUntil(long)等待最大时间是一个固定时间

import java.time.LocalDateTime;
import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程1:开始执行 |" + LocalDateTime.now());
            //当前时间 + 超时时间(唤醒时间)
            LockSupport.parkUntil(System.currentTimeMillis() + 3000);//3000ms代表3s,表示3s之后恢复执行
            System.out.println("线程1:结束执行 |" + LocalDateTime.now());
        },"线程1");
        t1.start();
    }
}

java线程如何被唤醒 java 唤醒指定线程_System_04

4.LockSupport和Interrupt

之前的 sleep/TimeUnit/wait 写法都需要加try-catch包裹来接收Interrupt异常,写法不够优雅;而 LockSupport.park/parkUntil在休眠时不需要try-catch包裹,不需要接收 Interrupt 异常。

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

try {
    TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
    e.printStackTrace();
}

synchronized (lock){
    try {
        lock.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

LockSupport.park();
LockSupport.parkUntil(1000 + System.currentTimeMillis());

LockSupport 不会抛出 Interrupt 的异常,但可以监听到 Interrupt 的通知:

import java.util.concurrent.locks.LockSupport;

public class ThreadDemo20 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            Thread currThread = Thread.currentThread();
            System.out.println("线程中止状态:" + currThread.isInterrupted());
            LockSupport.park();
            System.out.println("线程中止状态:" + currThread.isInterrupted());
        });
        t1.start();

        Thread.sleep(1000);
        System.out.println("中止线程");
        t1.interrupt();
        LockSupport.unpark(t1);
    }
}

java线程如何被唤醒 java 唤醒指定线程_java_05

5.LockSupport VS wait

相同点:

①二者都能使线程进入休眠状态。

②二者在不传递参数的情况下,都会让线程进入WAITING无限期等待状态。

不同点:

①LockSupport使用时不需要加锁,不需要配合synchronized一起使用;而wait需要配合synchronized一起使用。

②LockSupport不会抛出Interrupt的异常,而wait会。

③LockSupport可以指定某一个线程进行唤醒,而wait和notify不行。

PS:线程休眠4种方式:

  1. sleep(传参设置休眠时间;不可唤醒)
  2. TimeUnit(传参设置休眠时间;不可唤醒)
  3. wait/notify/notifyAll(可传参设置休眠时间,也可不传参无限等待;可以唤醒)
  4. LockSupport.park()/parkUntil(long)/unpark(thread)(parkUntil可传参设置休眠时间;park不传参无限等待;unpark传参唤醒指定线程)