线程间通信问题:
不同线程间针对
同一资源进行操作的问题
生产者消费者模型:
生产者(设置线程)和消费者(获取线程)对同一资源对象进行操作
实现:
一、学生类
Student.java
1
public class Student{
2
3
private String name;
4
private int age;
5
public Student(){
6
this.name = name;
7
this.age = age;
8
}
9
10
11
}
二、生产者类
SetThread.java
1
public class SetThread implements Runnable{
2
3
private Student s;
4
private count = 0;
5
public SetThread(Student s){
6
this.s = s;
7
}
8
@Override
9
public void run(){
10
while(true){
11
if(count%2==0){
12
s.name = "Mike";//设置资源属性
13
s.age = 20;
14
}else{
15
s.name = "Lily";//设置资源属性
16
s.age = 19;
17
}
18
19
}
20
21
}
22
23
}
三、消费者类
GetThread.java
1
public class GetThread implements Runnable{
2
3
private Student s;
4
5
6
public GetThread(Student s){
7
this.s = s;
8
}
9
@Override
10
public void run(){
11
12
System.out.println(s.name + "----" + s.age);
13
}
14
15
16
}
四、测试类
StudentTest.java
1
public void StudentTest{
2
3
public static void main(String[] agrs){
4
5
Student s = new Student("Mike",20);
6
7
SetThread st = new SetThread(s);
8
GetThread gt = new GetThread(s);
9
//开启线程
10
Thread t1 = new Thread(st);
11
Thread t2 = new Thread(gt);
12
t1.start();
13
t2.start();
14
15
}
16
17
}
产生问题:
1.只有t1线程先赋值,t2线程才能打印出值,否则t2打印出null
2.出现线程安全问题:1.共享资源 2.多线程 3.同时操作共享资源
解决问题:
1.对生产者(SetThread)、消费者(GetThread)都加锁---解决线程安全问题
2.加入等待唤醒机制------解决消费者线程比生产者线程先执行的问题(null的问题)
---------生产者:有产品(Student已赋值)则等待wait。没有产品(Student没有赋值)则生产赋值。
---------消费者:
有产品(Student已赋值)则消费。没有产品(Student没有赋值)则等待wait。
---------方法:wait() 和 notify()唤醒单个线程 notifyAll()唤醒所有线程
-------------------------------------------------------------------------------------------------------------
改进版
Student.java
1
public class Student{
2
3
private String name;
4
private int age;
5
private boolean hasData= false;//默认没有数据
6
public Student(){
7
this.name = name;
8
this.age = age;
9
}
10
11
12
}
改进版
SetThread.java
1
public class SetThread implements Runnable{
2
private Student s;
3
private count = 0;
4
public SetThread(Student s){
5
this.s = s;
6
}
7
@Override
8
public void run(){
9
while(true){
10
synchronized(s){//1.加锁解决线程安全问题
11
if(s.hasData){//2.生产者判断是否有数据
12
//已有数据,等待,并唤醒消费者消费
13
s.wait();
14
}
15
//没有数据,则赋值
16
s.hasData = true;
17
if(count%2==0){
18
s.name = "Mike";//设置资源属性
19
s.age = 20;
20
}else{
21
s.name = "Lily";//设置资源属性
22
s.age = 19;
23
}
24
s.notify();//唤醒消费者线程
25
}
26
27
28
}
29
30
}
31
}
改进版Get
Thread.java
1
public class GetThread implements Runnable{
2
private Student s;
3
4
public GetThread(Student s){
5
this.s = s;
6
}
7
@Override
8
public void run(){
9
synchronized(s){//1.加锁解决线程安全问题
10
if(s.hasData){//2.消费者判断是否有数据
11
//已有数据,消费
12
System.out.println(s.name + "----" + s.age);
13
s.notify();//唤醒消费者线程
14
}
15
//没有数据,则等待,并唤醒生产者生产数据
16
s.wait();
17
}
18
19
}
20
}
生产者消费者模型总结:
1.产生条件:生产者(线程1),消费者(线程2)对同一变量(产品)进行读写。
2.产生问题:
-------------生产者和消费者存在线程安全问题(生产者生产一半,CPU就让消费者消费)
-------------消费者要在生产者生产完后才能消费(出现消费者消费空产品的情况)
3.解决方法:
--------------生成者和消费者同时加锁(synchronized关键字对产品对象(student)加锁)
--------------等待唤醒机制