Java学习——并发编程之多线程之间通信

7 篇文章 0 订阅
5 篇文章 0 订阅

三.多线程之间通信

1.为什么有线程之间的通信?

(1)线程在运行时,cpu是随机调度的,往往我们会使用多个线程来完成同一个任务(类似多人协作),并且我们希望多线程完成任务是有规律的,那么在完成任务的过程中,线程之间必然要有一些交流,这样才能使用同一份数据进行操作。

(2)多线程使用同一份数据来完成任务,必然就会造成资源的争夺,所以引入线程的通信可以解决这样一个问题。

2.什么是线程之间的通信

多线程之间的通信就是多个线程共同操作同一个共享变量,一个线程在占用共享变量时,通知其他线程进行等待(wait()方法),使用完毕后,将其他线程唤醒(notify()和notifyall()方法)。这就是线程的等待唤醒机制wait()notify()。线程之间通信最典型的例子就是生产者与消费者问题。

3.wait、notify 方法

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

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

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

注意:一定要在线程同步中使用,并且是同一个锁的资源

4.演示生产者和消费者

package thread_demo3;
/**
 * 多线程之间通讯,生产者消费者
 * @author johson
 *  1.因为涉及到对象锁,他们必须都放在synchronized中来使用. Wait、Notify一定要在synchronized里面进行使用。
 *	2.Wait必须暂定当前正在执行的线程,并释放资源锁,让其他线程可以有机会运行
 *	3. notify/notifyall: 唤醒线程,使之运行
 *
 */

//生产的对象
class Person{
	String name;
	
	String sex;
	
	//flag==false时,只写不度
	//flag==true时,只读不写
	boolean flag = false;
	
}

//生产者进程
class writeThread extends Thread{
	
	public Person person;
	
	public writeThread(Person person) {
		this.person = person;
	}
	
	@Override
	public void run() {

		int count = 0;
		
		while(true){
			synchronized (person) {
				//当flag==true的时候,消费者去读取person
				if(person.flag){
					try {
						person.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				//当flag==false时,生产person,然后通知消费者去读取
				else {
					if(count == 0){
						person.name = "小红";
						person.sex = "女";
					}
					
					else {
						person.name = "小军";
						person.sex = "男";
					}
					
					System.out.println("生产者生产"+person.name+","+person.sex);
					
					count = (count+1)%2;
					
					person.flag = true;
					
					person.notify();
				}
			}

		}

	}
}

//消费者进程
class readThread extends Thread{
	
	public Person person;
	
	public readThread(Person person) {
		this.person = person;
	}
	
	@Override
	public void run() {
		while (true) {
			synchronized (person) {
				//flag==false时,等待生产者生产person
				if(!person.flag){
					try {
						person.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				//flag==true时,消费者读取person,然后将flag变成false,通知生产者去生产person
				else {
					System.out.println("消费者消费"+person.name+","+person.sex);
					person.flag = false;
					person.notify();
				}
				
			}
			
		}
	}
}

public class test1 {
	
	public static void main(String[] args) {
		//新建一个person对象
		Person person = new Person();
		//生产者
		writeThread write = new writeThread(person);
		//消费者
		readThread read = new readThread(person);
		
		write.start();
		
		read.start();
	}
	

}

运行结果如下:

5.waitsleep区别

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

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

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

(4)调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值