欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

线程通信及唤醒机制

程序员文章站 2024-03-02 16:00:16
...

线程间通信问题:

  •          不同种类的线程间针对同一资源的操作
    
  • 例:通过设置线程(生产者)和获取线程(消费者)针对同一个学生对象进行操作
  • 分析
  •  资源类:Student
    
  •  设置学生数据:SetThread(生产者)
    
  •  获取学生数据:GetThread(消费者)
    
  •  测试类:A生产者消费者问题
    
  • 线程安全问题
  •      1:是否多线程环境
    
  •      2:是否有共享数据
    
  •      3:是否有多条语句操作共享数据
    
  • 解决方案
  •    加锁
    
  •    注意:不同种类的线程都要加锁
    
  •         不同种类的线程加的锁必须是同一把锁 
    
  • 线程通信正常思路:
  •    A:生产者
    
  •           先看是否有数据,有就等待,没有就生产,生产完之后通知消费者来消费
    
  •    B:消费者 
    
  •           先看是否有数据,有就消费,没有就等待,通知生产者生产数据
    
  •           为了处理这种问题,java就提供了一种机制,等待唤醒机制 。
    

例:
public class StudentDemo{
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();
}

}
class Student{
String name;
int age;
}
class SetThread implements Runnable{
private Student s;
private int x=0;
public SetThread(Student s) {
this.s=s;
}
public void run() {
while(true) {
synchronized(s) {
if(x%2==0) {
s.name=“小程”;
s.age=21;
}else {
s.name=“小黄” ;
s.age=20;
}
x++;
}
}
}
}

class GetThread implements Runnable{
private Student s;
public GetThread(Student s) {
this.s=s;
}
public void run() {
while(true){
synchronized(s) {
System.out.println(s.name+"------"+s.age);
}
//不加锁
// 小黄------20
// 小程------20
// 小程------20
// 小程------21
// 小黄------20
// 小黄------20
// 小黄------21//姓名年龄不匹配,线程的随机性,需要加锁

			   //加锁后

// 小黄------20
// 小黄------20
// 小黄------20
// 小程------21
// 小程------21
}
}
}

等待唤醒机制:

  •      Object类中提供了三个方法(其他方法了解)
    
  •      wait():等待  有个小特点,当前线程等待了,就会释放锁
    
  •      notify():唤醒单个线程
    
  •      notifyAll():唤醒全部线程
    
  •    为什么这些方法不定义在Thread类中呢?
    
  •      这些方法必须通过锁对象调用,而我们刚才用的锁对象时任意锁对象
    
  •      所以这些方法必须定义在Object中 
    

例:
public class StudentDemo {
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();
}

}
class Student{
String name;
int age;
boolean flag;//默认false
}
class SetThread implements Runnable{
private Student s;
private int x=0;
public SetThread(Student s) {
this.s=s;
}
public void run() {
while(true) {
synchronized(s) {
//判断有没有(如果是true就是有)
if(s.flag) {
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(x%2==0) {
s.name=“小程”;
s.age=21;
}else {
s.name=“小黄” ;
s.age=20;
}
x++;
//修改标记
s.flag=true;
//唤醒线程
s.notify();
}
}
}
}

class GetThread implements Runnable{
private Student s;
public GetThread(Student s) {
this.s=s;
}
public void run() {
while(true){
synchronized(s) {
if(!s.flag) {
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(s.name+"------"+s.age);
//修改标记
s.flag=false;
//唤醒线程
s.notify();

       //加入唤醒机制后

// 小程------21
// 小黄------20
// 小程------21
// 小黄------20
// 小程------21
// 小黄------20
}
}
}
}

总结的一张线程转换图:线程通信及唤醒机制