欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(五)Java线程之间的通信之wait notify 及Condition用法await Signal

程序员文章站 2022-05-03 20:57:32
...

1.因为涉及到对象锁,他们必须都放在synchronized中来使用. Wait、Notify一定要在synchronized里面进行使用。

2.Wait必须暂定当前正在执行的线程,并释放资源锁,让其他线程可以有机会运行

3. notify/notifyall: 唤醒因锁池中的线程,使之运行

 

wait notify 

 * wait notify一定要放在同步代码块中执行|同步方法中执行
 * wait notify监视器对象必须为同一个对象

public class Demo31WaitAndNotify {
	private volatile int signal;

	public int getSignal() {
		return signal;
	}

	public void setSignal(int signal) {
		this.signal = signal;
	}
	
	public static void main(String[] args) {
		
		Demo31WaitAndNotify d = new Demo31WaitAndNotify();
		new Thread(new Runnable() {
			@Override
			public void run() {
				synchronized (d) {
					System.out.println(Thread.currentThread().getName()+" "+"Thread 修改状态执行....");
					try {
						Thread.sleep(3000L);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+" "+"Thread 修改状态成功!");
					d.setSignal(1);
					d.notify();
				}
			}
		}).start();
		
		
		new Thread(new Runnable() {
					@Override
					public void run() {
						synchronized (d) {
							//等待Signal信号为1开始执行,否则不能执行
							while(d.getSignal()!=1){
								try {
									d.wait();
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}
							//当信号为1时执行代码
							System.out.println(Thread.currentThread().getName() + " " + "模拟代码执行....");
						}	
					}
				}).start();
		}
	
	
}

Thread-0 Thread 修改状态执行....
Thread-0 Thread 修改状态成功!
Thread-1 模拟代码执行....

只有Thread-0执行完毕后进行notify之后,Thread-1才会执行。

经典范例eg:使用多线程循环打印abcabcabcabc...

public class Demo33ThreeMethodWaitAndNotify {
	private int signal;
	
	public synchronized void a(){
		while(signal !=0 ){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName()+" "+"a...");
		signal++;
		notifyAll();
	}
	
	public synchronized void b(){
		while(signal !=1 ){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName()+" "+"b...");
		signal++;
		notifyAll();
	}
	
	public synchronized void c(){
		while(signal !=2 ){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName()+" "+"c...");
		System.out.println("==========================================");
		signal=0;
		notifyAll();
	}
	
	public static void main(String[] args) {
		Demo33ThreeMethodWaitAndNotify demo = new Demo33ThreeMethodWaitAndNotify();
		A a = new A(demo);
		B b = new B(demo);
		C c = new C(demo);
		
		new Thread(a).start();
		new Thread(b).start();
		new Thread(c).start();
		
	}
}

class A implements Runnable {
	
	private Demo33ThreeMethodWaitAndNotify demo;
	
	public A(Demo33ThreeMethodWaitAndNotify demo) {
		this.demo = demo;
	}

	public void run() {
		while(true){
			demo.a();
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}


class B implements Runnable {
	
	private Demo33ThreeMethodWaitAndNotify demo;
	
	public B(Demo33ThreeMethodWaitAndNotify demo) {
		this.demo = demo;
	}

	public void run() {
		while(true){
			demo.b();
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}


class C implements Runnable {
	
	private Demo33ThreeMethodWaitAndNotify demo;
	
	public C(Demo33ThreeMethodWaitAndNotify demo) {
		this.demo = demo;
	}

	public void run() {
		while(true){
			demo.c();
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

 

waitsleep区别

对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。

sleep()方法导致了程序暂停执行指定的时间,让出cpu给其它线程,但是它的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。

在调用sleep()方法的过程中,线程不会释放对象锁。

而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备

获取对象锁进入运行状态。

(五)Java线程之间的通信之wait notify 及Condition用法await Signal

Lock锁

在 jdk1.5 之后,并发包中新增了 Lock 接口(以及相关实现类)用来实现锁功能,Lock 接口提供了与 synchronized 关键字类似的同步功能,但需要在使用时手动获取锁和释放锁。

Lock写法

Lock lock  = new ReentrantLock();

lock.lock();

try{

//可能会出现线程安全的操作

}finally{

//一定在finally中释放锁

//也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常

  lock.ublock();

}

 

Locksynchronized 关键字的区别

Lock 接口可以尝试非阻塞地获取锁 当前线程尝试获取锁。如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。
Lock 接口能被中断地获取锁 与 synchronized 不同,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。

Lock 接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。

Condition用法

 Condition的功能类似于在传统的线程技术中的,Object.wait()和Object.notify()的功能。

Condition condition = lock.newCondition();

res. condition.await();  类似wait

res.Condition. Signal() 类似notify

/**
 * 31Condition的使用及原理解析
 * @author Administrator
 * notify随机唤醒等待线程中的一个 condition(AQS)可以唤醒指定的线程。
 * java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject
 * -await
 * -signal
 * -signalAll
 * 
 * print abcabcabcabc
 *
 */
public class Demo34ThreeMethodWaitAndNotify {
	private int signal=0;
	Lock lock = new  ReentrantLock();
	Condition a = lock.newCondition();
	Condition b = lock.newCondition();
	Condition c = lock.newCondition();
	public void a(){
		lock.lock();
		while(signal !=0 ){
			try {
				a.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName()+" "+"a...");
		signal++;
		b.signal();
		lock.unlock();
	}
	
	public void b(){
		lock.lock();
		while(signal !=1 ){
			try {
				b.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName()+" "+"b...");
		signal++;
		c.signal();
		lock.unlock();
	}
	
	public void c(){
		lock.lock();
		while(signal !=2 ){
			try {
				c.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName()+" "+"c...");
		System.out.println("==========================================");
		signal=0;
		a.signal();
		lock.unlock();
	}
	
	public static void main(String[] args) {
		Demo34ThreeMethodWaitAndNotify demo = new Demo34ThreeMethodWaitAndNotify();
		A a = new A(demo);
		B b = new B(demo);
		C c = new C(demo);
		
		new Thread(a).start();
		new Thread(b).start();
		new Thread(c).start();
		
	}
}

class A implements Runnable {
	
	private Demo34ThreeMethodWaitAndNotify demo;
	
	public A(Demo34ThreeMethodWaitAndNotify demo) {
		this.demo = demo;
	}

	public void run() {
		while(true){
			demo.a();
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}


class B implements Runnable {
	
	private Demo34ThreeMethodWaitAndNotify demo;
	
	public B(Demo34ThreeMethodWaitAndNotify demo) {
		this.demo = demo;
	}

	public void run() {
		while(true){
			demo.b();
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}


class C implements Runnable {
	
	private Demo34ThreeMethodWaitAndNotify demo;
	
	public C(Demo34ThreeMethodWaitAndNotify demo) {
		this.demo = demo;
	}

	public void run() {
		while(true){
			demo.c();
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

 

相关标签: 多线程 java