zoukankan      html  css  js  c++  java
  • Java中如何唤醒“指定的“某个线程

    熟悉线程操作的小朋友应该知道,Java中线程的挂起和唤醒一般用synchronized + wait + notify完成。

    比如:

    synchronized(o) {
    
        o.wait(); //wait状态
    
    }

    在其他线程中o.notify(),就可以唤醒在o上wait的线程。

    可是如果o上有多个线程wait,是没有办法唤醒“指定”的某个线程的。

    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();
        }
    }

    (2)使用Lock + Condition 实现唤醒指定的部分线程

    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();
        }
    }

    console输出:

     (3) 使用Java6引入的LockSupport这个类。

    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态
        }
    }

  • 相关阅读:
    Python——String类型操作符
    NLTK——NLP流程
    NLTK——常用函数
    Java——IO流 对象的序列化和反序列化流ObjectOutputStream和ObjectInputStream
    java——什么是浅表副本
    JavaWeb——<c:forEach varStatus="status">
    kubernetes安装
    [转]Jmeter + Grafana + InfluxDB 性能测试监控
    html转markdown网站
    golang的包管理---vendor/dep等
  • 原文地址:https://www.cnblogs.com/myseries/p/12531986.html
Copyright © 2011-2022 走看看