黑马程序员——多线程之线程间的通信

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

线程间通信实例

需求:
	一个线程作为生产者提供信息(如学生的注册信息),
	另一个线程作为消费者获取信息(如获取学生信息),且保证提供一个获取一个
       主要问题:不同种类的线程间针对同一个资源的操作。

 
  
 
  

 
  
 	A:对象必须是外部创建并以参数提供,才可以保证数据的统一
 	B:因为是使用线程实现,所以代码只能是写在run()方法中的,使用start调用run方法即可。
 	C:由于存在线程安全问题:
 			多线程环境
 			共享资源
 			多个代码处理资源
 		所以要使用同步解决线程安全问题。锁使用了资源对象
 	D:最后实现了信息正确输出,但是没有逐条获取和输出,怎么可以实现设置一个获取一个呢?
 		通过Java提供的等待唤醒机制解决。等待唤醒都是由锁对象来执行的。
 		等待唤醒:Object类中提供了三个方法:
 * 			wait():等待
 * 			notify():唤醒单个线程
 * 			notifyAll():唤醒所有线程
 * 		为什么这些方法不定义在Thread类中呢?
 * 			这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。
 * 			所以,这些方法必须定义在Object类中。
 */

 
  

实现:

同步机制解决线程安全,等待唤醒机制解决通信问题

 	A:写一个Student的类,该类中把成员变量私有
 		提供set和get的设置和获取信息的方法
 		由于是线程实现,所以要写成同步方法
 		使用等待唤醒机制保证正常通信(依次设置和获取)
public class Student {

	private String name;
	private int age;
	private boolean flag;//首先定义一个标记:如果为true则有数据,为false则没有数据

	// 把设置和获取的操作给封装成了功能,且是同步功能,
	//这里只是把功能封装成同步的,具体的线程要在调用方法的类中定义
	
	public synchronized void set(String name, int age) {
		// 如果已经设置过数据了则等待
		if (this.flag == true) {
			try {
				// 因为此时的锁是this
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 赋值
		this.name = name;
		this.age = age;

		// 更改标签
		this.flag = true;
		// 唤醒取值进程
		this.notify();
	}
	
	public synchronized void get(){
		//如果没有赋值则等待
		if(!this.flag){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//取值
		System.out.println(this.name+"---"+this.age);
		//更改标签
		this.flag=false;
		//唤醒赋值进程
		this.notify();
	}
}
 	B:创建设置和获取信息的类,该类实现Runnable接口
 		在run方法中调用set和get方法
 		由于数据源是统一的,所以该类要提供带参构造传递资源对象
public class SetThread implements Runnable {

	private Student s;

	public SetThread(Student s) {
		this.s = s;
	}

	private int x = 0;

	@Override
	public void run() {
		while (true) {
			if (x % 2 == 0) {
				s.set("carry", 18);
			} else {
				s.set("tony", 20);
			}
			x++;
		}
	}

}
public class GetThread implements Runnable {

	private Student s;

	public GetThread(Student s) {
		this.s = s;
	}

	@Override
	public void run() {
		while (true) {
			s.get();
		}
	}

}
外部创建对象并以参数提供,保证数据的统一

 	C:测试类首先要创建资源,然后把资源对象作为参数传递给实现Runnable接口的类,然后创建线程对象开启线程
public class ThreadCom {

	public static void main(String[] args) {
		// 创建资源
		Student s = new Student();
		// 创建设置和获取的类对象
		SetThread st = new SetThread(s);
		GetThread gt = new GetThread(s);
		// 创建线程对象
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(gt);
		//开启线程
		t1.start();
		t2.start();
	}
}

你可能感兴趣的:(java基础)