多线程学习笔记(二)---- 线程之间的通信

一、前言

多个线程在处理同一个资源,但是任务却不同

二、场景1

1、介绍

打印出一个资源,一个任务是输入资源信息,另一个任务是输出资源信息

2、代码实现

//资源对象
public class Resource {
	String name;
	String sex;
}
public class Input implements Runnable{
	//资源
	private Resource r;
	
	public Input(Resource r){
		this.r = r;
	}
	
	//任务
	public void run(){
		int x = 0;
		while(true){
			
			synchronized (r) {
				if(x == 0){
					r.name = "mike";
					r.sex = "nan";
				}else{
					r.name = "丽丽";
					r.sex = "女女女女";
				}
			}
			
			x = (x+1)%2;
		}
	}
}
//输出任务
public class Output implements Runnable{
	//资源
	private Resource r;
	
	//
	public Output(Resource r){
		this.r = r;
	}
	
	//任务
	public void run(){
		while(true){
			synchronized (r) {
				System.out.println(r.name+"....."+r.sex);
			}
		}
	}
}
//测试
public class Demo {
	public static void main(String[] args) {
		//资源
		Resource r = new Resource();
		
		//不同任务对象
		Input input = new Input(r);
		Output output = new Output(r);
		
		//多个线程
		Thread test1 = new Thread(input);
		Thread test2 = new Thread(output);
		
		test1.start();
		test2.start();
	}
}

注意:
这里的线程任务是有需要同步执行的代码,而这个代码块的锁不能是我们随意new的一个对象!!!因为这是不同的任务,但需要同步执行,所有这俩个任务必须使用同一把锁。这里的资源对象就是最好的锁。所以,以后同步代码块的锁还是用同一资源对象较好。

三、场景2

1、介绍

我们需要每一次Resource有新值的时候,必须先打印出来,才能再次赋值

2、等待/唤醒机制

  • wait():让线程处于冻结状态,被wait的线程会被存储到线程池中。这个线程池就是这个锁的线程池;
  • notify():唤醒线程池中一个线程,该线程有JVM选择;
  • notifyAll():唤醒线程池中的所有线程;

3、代码实现

//资源文件
public class Resource {
	String name;
	String sex;
        //为true,表示name、sex有新值;为flase,表示name、sex无新值
	boolean flag = false;
}
public class Input implements Runnable{
	//资源
	private Resource r;
	
	public Input(Resource r){
		this.r = r;
	}
	
	//任务
	public void run(){
		int x = 0;
		while(true){
			
			synchronized (r) {
                //如果资源有新值,不允许加新值,使该线程休眠
				if(r.flag){
					try {
						r.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}

				//向资源赋新值
				if(x == 0){
					r.name = "mike";
					r.sex = "nan";
				}else{
					r.name = "丽丽";
					r.sex = "女女女女";
				}
				x = (x+1)%2;
				//唤醒输出线程
                r.flag = true;//保证在没有输出之前,该线程再次被调用时,让该线程处理休眠状态
				r.notify();
			}
		}
	}
}
//输出任务
public class Output implements Runnable{
	//资源
	private Resource r;
	
	//
	public Output(Resource r){
		this.r = r;
	}
	
	//任务
	public void run(){
		while(true){
			synchronized (r) {
                //如果该资源没有新值,就使该线程休眠
				if(!r.flag){
					try {
						r.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
                //输出资源的新值
				System.out.println(r.name+"....."+r.sex);
				//唤醒输入线程
				r.flag = false;//保证在没有新值的资源下,使该线程休眠
				r.notify();
			}
		}
	}
}
//测试
public class Demo {
	public static void main(String[] args) {
		//资源
		Resource r = new Resource();
		
		//不同任务对象
		Input input = new Input(r);
		Output output = new Output(r);
		
		//多个线程
		Thread test1 = new Thread(input);
		Thread test2 = new Thread(output);
		
		test1.start();
		test2.start();
	}
}

你可能感兴趣的:(多线程学习笔记(二)---- 线程之间的通信)