java 线程——线程的通信

线程通信的三种方式

同步

while 轮询方式

wait() / notify() 方式


线程通信的三种方式

同步

这里讲的同步是synchronized 关键字来实现线程间的通信,我们用代码来示范一下。

class Obj{
	int count = 0;
	public synchronized void add(){
		//do something
		count++;
	}
	public synchronized void del(){
		//do something
		count--;
	}
}
public class Demo4 {
	static Obj obj = new Obj();
	public static void main(String[] args) {
		//线程1
		new Thread(new Runnable(){
			public void run() {
				for(int i = 0;i < 10;i++){
					obj.add();
				}
			}
		}).start();
		//线程2 
		new Thread(new Runnable(){
			public void run() {
				for(int i = 0;i < 5;i++){
					obj.del();
				}
			}
		}).start();
		//主线程
		while(Thread.activeCount() > 1){
			Thread.yield();
		}
		System.out.println("main:"+obj.count);
	}
} 

我们来分析一下上面的代码,线程1 和线程2 都是对obj 这个对象进行操作,当线程1 执行add()方法的时候拿到了obj 这个对象作为锁,此时线程2 不能进行del()方法。当线程1 执行完了add()方法之后线程2 才能运行,这样就实现了线程间的通信。

这种方法本质上是共享变量式通信,谁拿到了锁谁就可以执行。

while 轮询方式

这种方式是两个线程一个线程不断地改变条件,另一个线程里有一个while 循环,不断判断条件,直到条件成立,开始执行执行其他的代码块,其实这就是多个线程同时执行,这中方式会牺牲部分CPU性能。

class Obj{
	int count = 0;
	public synchronized void add(){
		//do something
		count++;
	}
	public synchronized void del(){
		//do something
		count--;
	}
}
public class Demo4 {
	static Obj obj = new Obj();
	public static void main(String[] args) {
		//线程1
		new Thread(new Runnable(){
			@Override
			public void run() {
				for(int i = 0;i < 10;i++){
					obj.add();
					System.out.println("++");
				}
			}
		}).start();
		//线程2
		new Thread(new Runnable(){
			@Override
			public void run() {
				boolean b = true;
				while(b){
					if(obj.count == 5){
						System.out.println("线程2 退出了");
						b = false;
					}
				}
			}
		}).start();;
	}
	

上面的代码中,当线程2 的条件不满足时,它一直在进行无意义的循环。

wait() / notify() 方式

这种方式有一个经典的例子就是生产者—消费者模型,当仓库货物不足时,消费者就要等待,生产者生产足够的货物是给消费者发送一个消息,消费者才可以继续运行。同样,当仓库满了之后生产者就需要停止一段时间,等到一部分货物消费出去之后消费者发送消息给生产者,表示生产者可以继续工作了。

class Model {
	private int count;
	public Model(){
		this.count = 1000;
	}
	
	public synchronized void produce(int val){
		if(count > 5000){
			try {
				System.out.println("仓库已满");
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			count += val;
			System.out.println("生产 1000-当前容量:"+get());
			this.notify();
		}
	}

	public synchronized void consume(int val){
		if(count < val){
			System.out.println("容量不足-当前容量:"+get());
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			count -= val;
			System.out.println("消费 2000-仓库容量:"+get());
			this.notifyAll();
		}
		
	}
	public int get(){
		return this.count;
	}
}
public class Demo8 {
	public static void main(String[] args) {
		
		final Model model = new Model();
		 /**
		  * 生产者
		  */
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					model.produce(1000);
				}
			}
		}).start();
		
		/**
		 * 消费者
		 */
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){	
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					model.consume(2000);
				}
			}
		}).start();
	}
}

运行结果:

容量不足-当前容量:1000
生产 1000-当前容量:2000
消费 2000-仓库容量:0
生产 1000-当前容量:1000
容量不足-当前容量:1000
生产 1000-当前容量:2000
生产 1000-当前容量:3000
消费 2000-仓库容量:1000
生产 1000-当前容量:2000
消费 2000-仓库容量:0
生产 1000-当前容量:1000
容量不足-当前容量:1000
生产 1000-当前容量:2000
消费 2000-仓库容量:0

猜你喜欢

转载自blog.csdn.net/Alyson_jm/article/details/82812074