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


浙公网安备 33010602011771号