Java中如何唤醒“指定的“某个线程

线程状态

  • NEW(初始化状态) 

线程通过new初始化完成到调用start方法前都处于等待状态。

  • RUNNABLE(可执行状态) 

线程执行start方法后就处于可以行状态。

  • BLOCKED(阻塞状态) 

notify方法被调用后线程被唤醒,但是这时notify的synchronized代码段并没有执行完,同步锁没有被释放,所以线程处于BLOCKED状态。直到notify的synchronized代码段执行完毕锁被释放,线程才回到wait所在的synchronized代码段继续执行。

  • WAITING(等待状态) 

调用sleep或是wait方法后线程处于WAITING状态,等待被唤醒。

  • TIMED_WAITING(等待超时状态) 

调用sleep或是wait方法后线程处于TIMED_WAITING状态,等待被唤醒或时间超时自动唤醒。

  • TERMINATED(终止状态) 

在run方法结束后线程处于结束状态。

方法一、使用Lock + Condition 实现唤醒指定的部分线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
public class Test {
    public static Lock lock = new ReentrantLock();
    public static int count = 0;
     
    public static Condition conditionA = lock.newCondition();
    public static Condition conditionB = lock.newCondition();
     
    public static void main(String[] args) {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                lock.lock();
                if (count < 5) {
                    System.out.println("线程1未达到业务要求,暂停中,等待线程2处理到达到要求后唤醒");
                    try {
                        conditionA.await();// 暂停线程并释放锁
                        System.out.println("conditionA被唤醒");
                        conditionB.await();
                        System.out.println("conditionB被唤醒");
                        System.out.println("我是线程1后面的代码");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.unlock();
            }
        };
         
        Thread t2 = new Thread() {
            @Override
            public void run() {
                lock.lock();
                while (count < 10) {
                    count++;
                    System.out.println("线程2业务处理中: " + count);
                    try {
                        Thread.sleep(1000);
                        if (count == 5) {
                            conditionA.signal();
                            System.out.println("唤醒线程1");
                            lock.unlock();// 调用signal()方法后,线程2并不会释放锁,需要手动释放线程2才会执行
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    lock.lock();// 不加这个会报java.lang.IllegalMonitorStateException
                    System.out.println("等待3秒后conditionB会被唤醒");
                    Thread.sleep(3000);
                    conditionB.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock.unlock();// 这里释放锁,线程2执行完,线程1才会执行
            }
        };
         
        t1.start();
        t2.start();
    }
}

方法二、使用Java6引入的LockSupport这个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.concurrent.locks.LockSupport;
 
public class TestLockSupport {
 
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            System.out.println("start");
            LockSupport.park(); //一直wait
            System.out.println("continue");
        });
         
        t.start();
        Thread.sleep(2000);
        LockSupport.unpark(t); //指定t线程解除wait态
    }
}

方法三、synchronized + wait + notify

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.util.concurrent.TimeUnit;
 
public class TestNotify extends Thread{
     
    public static void main(String[] args) {
        final Object synObj = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(synObj) {
                    System.out.println("1.T1获取synObj的对象监视器,开始执行同步块");
                    try {
                        TimeUnit.SECONDS.sleep(2);//休息一分钟,不放弃锁
                        System.out.println("T1在 wait()时挂起了");
                        synObj.wait();
                        System.out.println("T1被其他线程唤醒后并重新获得synObj的对象监视器,继续执行");
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("T1获取synObj的对象监视器,结束同步块");
                }
            };
        });
        t1.start();
 
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("T2启动,但是因为有别的线程占用了synObj的对象监视器,则等待别的线程执行synObj.wait来释放它");
                synchronized(synObj) {
                    try {
                        System.out.println("T2获取synObj的对象监视器,进入同步块");
                        synObj.notify();
                        System.out.println("T2执行synObj.notify()");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println("T2结束同步块,释放synObj的对象监视器");
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
        });
        t2.start();
         
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("T3启动,但是因为有别的线程占用了synObj的对象监视器,则等待别的线程执行synObj.wait来释放它");
                synchronized(synObj) {
                    try {
                        System.out.println("T3获取synObj的对象监视器,进入同步块");
                        synObj.notify();
                        System.out.println("T3执行synObj.notify()");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println("T3结束同步块,释放synObj的对象监视器");
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
        });
        t3.start();
    }
}

  

posted on   书梦一生  阅读(2797)  评论(0编辑  收藏  举报

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示