Java使用Condition唤醒指定线程

使用ReentrantLock实现同步

首先创建一个功能类,用于实现线程的功能


public class MyService {
	private Lock lock = new ReentrantLock();
	public void methodA() {
		try {
			lock.lock();  //加锁,作用相当于synchronized
			
			System.out.println(Thread.currentThread().getName()+" 进入methodA  并得到锁");
			
			Thread.sleep(2000);
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			System.out.println(Thread.currentThread().getName()+" 离开methodA  并释放锁");
			lock.unlock(); //释放锁
		}
		
	}
	
	public void methodB() {
		try {
			lock.lock();
			System.out.println(Thread.currentThread().getName()+" 进入methodB  并得到锁");
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			System.out.println(Thread.currentThread().getName()+" 离开methodB  并释放锁");
			lock.unlock();
		}
		
	}
}


创建的四个线程,两个运行methodA,两个运行methodB

public static void main(String[] args) {
		final MyService service = new MyService();
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				service.methodA();
			}

		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				service.methodA();
			}

		}).start();
		
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				service.methodB();
			}

		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				service.methodB();
			}

		}).start();

	}

运行结果:

Thread-0 进入methodA  并得到锁
Thread-0 离开methodA  并释放锁
Thread-1 进入methodA  并得到锁
Thread-1 离开methodA  并释放锁
Thread-2 进入methodB  并得到锁
Thread-2 离开methodB  并释放锁
Thread-3 进入methodB  并得到锁
Thread-3 离开methodB  并释放锁


目前来看,lock和unlock之间是被锁定的,这一点和关键字synchronized作用相同



使用Condition唤醒指定线程

synchronized关键字与wait()和notify()/notifyAll()结合能够实现等待通知模型,但是却面临一个问题,就是,被wait()唤醒的线程是随机的,而notifyAll()唤醒的又是所有的,不能唤醒指定的线程。

ReentrantLock借助于Condition就可以实现唤醒指定线程,这样在线程调度上更加灵活。


public class MyService {
	private Lock lock = new ReentrantLock();
	private Condition condition  = lock.newCondition();
	private Condition condition2 = lock.newCondition();
	public void await1() {
		try {
			lock.lock();
			System.out.println("执行 await1 方法");
			condition.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			System.out.println("await1 锁释放了");
		}
	}
	
	public void await2() {
		try {
			lock.lock();
			System.out.println("执行 await2 方法");
			condition2.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			System.out.println("await2锁释放了");
		}
	}
	
	public void signal1() {
		try {
			lock.lock();
			System.out.println("执行signal1方法");
			condition.signal();
			System.out.println("通知了await1 ");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			
		}
	}
	
	public void signal2() {
		try {
			lock.lock();
			System.out.println("执行signal2方法");
			condition2.signal();
			System.out.println("通知了await2 ");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			
		}
	}
}

四个线程类

public class ThreadA extends Thread{
	private MyService service;
	public ThreadA(MyService service) {
		this.service = service;
	}
	
	public void run() {
		service.await1();
	}
}

public class ThreadAA extends Thread{
	private MyService service;
	public ThreadAA(MyService service) {
		this.service = service;
	}
	
	public void run() {
		service.await2();
	}
}
ThreadB用于唤醒由condition等待的线程
public class ThreadB extends Thread{
	private MyService service;
	public ThreadB(MyService service) {
		this.service = service;
	}
	
	public void run() {
		service.signal1();
	}
}
threadBB用于唤醒由condition2等待的线程
public class ThreadBB extends Thread {
	private MyService service;
	public ThreadBB(MyService service) {
		this.service = service;
	}
	
	public void run() {
		service.signal2();
	}
}


public static void main(String[] args) {
	MyService service = new MyService();
	ThreadA threadA = new ThreadA(service);
	ThreadAA threadAA = new ThreadAA(service);
	ThreadB threadB = new ThreadB(service);
	ThreadBB threadBB = new ThreadBB(service);
	
	try {
		threadA.start();
		threadAA.start();
		Thread.sleep(300);
		threadB.start();
		ThreadA.sleep(3000);
		threadBB.start();
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
}




运行结果:


执行 await1 方法
执行 await2 方法
执行signal1方法    //threadB只唤醒了由condition等待的线程
通知了await1 
await1 锁释放了
执行signal2方法
通知了await2 
await2锁释放了


  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中,notify() 方法只能随机唤醒一个在该对象上等待的线程,而无法指定唤醒某个特定的线程。如果需要唤醒特定的线程,可以使用 Condition 对象来实现。Condition 对象是 Java 5 中新增的一个类,它提供了类似于 Object 类的 wait() 和 notify() 方法的功能,但是它可以更精确地控制等待和唤醒线程Condition 对象提供了 await() 方法和 signal() 方法,分别用于等待和唤醒线程。 下面是一个使用 Condition 对象唤醒特定线程的示例代码: ``` java import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ThreadTest { private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); public void method1() throws InterruptedException { lock.lock(); try { System.out.println("Thread 1 is waiting..."); condition1.await(); System.out.println("Thread 1 is resumed."); } finally { lock.unlock(); } } public void method2() throws InterruptedException { lock.lock(); try { System.out.println("Thread 2 is waiting..."); condition2.await(); System.out.println("Thread 2 is resumed."); } finally { lock.unlock(); } } public void signal1() { lock.lock(); try { condition1.signal(); } finally { lock.unlock(); } } public void signal2() { lock.lock(); try { condition2.signal(); } finally { lock.unlock(); } } public static void main(String[] args) throws InterruptedException { ThreadTest test = new ThreadTest(); Thread thread1 = new Thread(() -> { try { test.method1(); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread thread2 = new Thread(() -> { try { test.method2(); } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); thread2.start(); Thread.sleep(1000); test.signal2(); } } ``` 在上述代码中,使用了两个 Condition 对象 condition1 和 condition2 来分别控制两个方法的等待和唤醒。在 main() 方法中,先启动了两个线程并让它们进入等待状态,然后调用了 signal2() 方法来唤醒第二个线程。由于唤醒的是 condition2 上等待的线程,因此只有第二个线程会被唤醒,而第一个线程仍然处于等待状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值