Java多线程再学习,温故知新(八)线程之间的通信之wait notify

线程之间的通信

     线程通信的目标实际上是线程直接能够互相发送信号,线程在接收到信号后执行特定的逻辑,信号可以是线程直接可见的变量;

     也可以说线程直接有一些关联的操作,比如A,B两个线程,B线程需要等A线程执行完毕后在接着执行。

      线程实现的方式:

     1.使用自旋的方式

public class Demo {
	
	private volatile int signal;
	
	public void set (int value) {
		this.signal = value;
	}
	
	public int get () {
		return signal;
	}
	
	public static void main(String[] args) {
		Demo d = new Demo();
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				System.out.println("修改状态的线程执行...");
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				d.set(1);
				System.out.println("状态值修改成功。。。");
			}
		}).start();
		
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				// 等待signal为1开始执行,否则不能执行
				while(d.get() != 1) {
					try {
						Thread.sleep(1500);//休眠一会减少CPU的自旋消耗
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				// 当信号为1 的时候,执行代码
				System.out.println("模拟代码的执行...");
				
			}
		}).start();
	}
}

      2.使用wait和notify,注意:使用的时候一定要放到同步synchrnoized代码块中使用。      

public class Demo2 {
	
	private volatile int signal;
	
	public void set (int value) {
		this.signal = value;
	}
	
	public int get () {
		return signal;
	}
	
	public static void main(String[] args) {
		Demo2 d = new Demo2();
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				synchronized (d) {
					System.out.println("修改状态的线程执行...");
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					d.set(1);
					System.out.println("状态值修改成功。。。");
					d.notify();
				}
			}
		}).start();
		
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				synchronized (d) {
					// 等待signal为1开始执行,否则不能执行
					while(d.get() != 1) {
						try {
							d.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					// 当信号为1 的时候,执行代码
					System.out.println("模拟代码的执行...");
				}
			}
		}).start();
	}
}

     3.注意:

       wait方法会释放同步代码块synchronized的锁

       notify方法会随机叫醒一个处于wait状态的线程,唤醒的线程会拿到锁

       notifyAll叫醒所有的处于wait线程,争夺到时间片的线程只有一个

public class Target1 implements Runnable {
	
	private Demo3 demo;
	
	public Target1(Demo3 demo) {
		this.demo = demo;
	}

	@Override
	public void run() {
		demo.set();
	}

}
public class Target2 implements Runnable {
	
	private Demo3 demo;

	public Target2(Demo3 demo) {
		this.demo = demo;
	}

	@Override
	public void run() {
		demo.get();
	}
}

import java.util.concurrent.TimeUnit;

public class Demo3 {

private volatile int signal;
	
	public synchronized void set () {
		signal = 1;
		notifyAll(); // notify方法会随机叫醒一个处于wait状态的线程
		 // notifyAll叫醒所有的处于wait线程,争夺到时间片的线程只有一个
		System.out.println("叫醒线程叫醒之后休眠开始...");
		try {
			Thread.sleep(3000);//这里睡眠后方法的锁还没释放,只有等方法执行后,notifyAll通知的线程才会继续执行
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public synchronized int get () {
		System.out.println(Thread.currentThread().getName() + " 方法执行了...");
		if(signal != 1) {
			try {
				wait();
				System.out.println("叫醒之后");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + " 方法执行完毕...");
		return signal;
	}
	
	public static void main(String[] args) {
		
		Demo3 d = new Demo3();
		Target1 t1 = new Target1(d);
		Target2 t2 = new Target2(d);
		
		new Thread(t2).start();
		new Thread(t2).start();
		new Thread(t2).start();
		new Thread(t2).start();
		
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		new Thread(t1).start();
	}
}

生产者消费者模式

 

//生产者
public class PushTarget implements Runnable {

	private Tmall tmall;
	
	public PushTarget(Tmall tmall) {
		this.tmall = tmall;
	}
	
	@Override
	public void run() {
		while(true) {
			tmall.push();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
//消费者
public class TakeTarget implements Runnable {
	
	private Tmall tmall;
	
	public TakeTarget(Tmall tmall) {
		this.tmall = tmall;
	}

	@Override
	public void run() {
		while(true) {
			tmall.take();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

处理生产者和消费者数据

public class Tmall {
	
	private int count;
	
	public final int MAX_COUNT = 10;
	
	public synchronized void push () {
		while(count >= MAX_COUNT) {
			try {
				System.out.println(Thread.currentThread().getName() + " 库存数量达到上限,生产者停止生产。");
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		count ++;
		System.out.println(Thread.currentThread().getName() + " 生产者生产,当前库存为:" + count);
		notifyAll();//通知消费者去消费
	}
	
	public synchronized void take () {
		
		while(count <= 0) {
			try {
				System.out.println(Thread.currentThread().getName() + " 库存数量为零,消费者等待。");
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		count --;
		System.out.println(Thread.currentThread().getName() + " 消费者消费,当前库存为:" + count);
		notifyAll();//叫醒生产者继续叫醒
	}
}

测试类

public class Main {
	
	public static void main(String[] args) {
		
		Tmall tmall = new Tmall();
		
		PushTarget p = new PushTarget(tmall);
		TakeTarget t = new TakeTarget(tmall);
		
		new Thread(p).start();
		new Thread(p).start();
		new Thread(p).start();
		new Thread(p).start();
		new Thread(p).start();
		
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
	}
}

 

猜你喜欢

转载自blog.csdn.net/ieflex/article/details/86688634