------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
线程间通信实例
需求:
一个线程作为生产者提供信息(如学生的注册信息),
另一个线程作为消费者获取信息(如获取学生信息),且保证提供一个获取一个<pre name="code" class="java"> 主要问题:不同种类的线程间针对同一个资源的操作。
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();
}
}