目录
一:死锁
1:概念
是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象。
2:产生死锁原因
同步弊端
效率低
如果出现了同步嵌套,就容易产生死锁问题
3:例子
如果完成一件事情需要两个工具,两个人同时工作当两个人同时拥有一个工具然后找另一个工具,由工具都在对方手中会找不到就会一直等待有工具资源,就会出现死锁。
二:线程通信
1:概念
针对同一个资源的操作有不同种类的线程
线程有生产者和消费者这样的问题称之为通信问题
2:线程间通信的代码改进
A:通过等待唤醒机制实现数据依次出现(等待唤醒方法在object类中)
B:把同步代码块改进为同步方法实现
3:等待唤醒机制
如何添加等待唤醒机制呢?
Object类中有三个方法:
void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
void notify() 唤醒正在等待对象监视器的单个线程。
void notifyAll() 唤醒正在等待对象监视器的所有线程。
4:例子
学生设置名字和取名字
分析:设置名字是生产者,取名字是消费者,取名字要在设置名字之后,或者说应该设置好名字以后再取名字。
package day33;
public class Student {
int age;
String name;
boolean f;
public Student() {
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
package day33;
/*创建GetName实现Runnable接口将学生对象当作参数传入*/
public class SetName implements Runnable{
private Student s;
int x=0;
public SetName(Student s){
this.s=s;
}
@Override
public void run() {
while (true) {
synchronized (s) {
//当有值时等待,没有值时去赋值奇数次赋值李焕偶数次赋值丽华
if(s.f){
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (x % 2 == 0) {
s.age = 18;
s.name = "李焕";
} else {
s.age = 17;
s.name = "丽华";
}
x++;
s.notify();
s.f=true;
}
}
}
}
package day33;
/*创建GetName实现Runnable接口将学生对象当作参数传入*/
public class GetName implements Runnable{
private Student s;
public GetName(Student s){
this.s=s;
}
@Override
public void run() {
while (true){ synchronized (s){
//当没有值时等待否则进入取值值时进入取值
if(!s.f){
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(s.name+"**"+s.age);
s.notify();
s.f=false;
}
}
}}
package day33;
public class Test {
public static void main(String[] args) {
//创建线程对象将学生对象传入
Student student = new Student();
GetName getName = new GetName(student);
SetName setName = new SetName(student);
Thread pro = new Thread(setName);
Thread cus = new Thread(getName);
//启动线程
cus.start();
pro.start();
}
}