/*
* Person类 姓名 性别
* 开启两个线程
* 一个对Person对象进行赋值
* 一个对Person对象进行打印
* 要求
* 一次打印 丁鹏 男
* 一次打印 dingpeng nv
* 间隔输出
*
* 1.先保证要操作的是同一个对象
* 2.要保证数据安全需要使用锁,并且要使用同一把锁
* 3.保证操作的逻辑顺序要对(先赋值,在打印)用 wait 和 notify
*/
public class Demo06 {
public static void main(String[] args) {
// 创建对象(只能使用同一个对象)
Person person = new Person();
// 创建线程
SetRunnable setRunnable = new SetRunnable(person);
Thread thread1 = new Thread(setRunnable);
PrintRunnable printRunnable = new PrintRunnable(person);
Thread thread2 = new Thread(printRunnable);
thread1.start();
thread2.start();
}
}
// 赋值线程
class SetRunnable implements Runnable {
// 利用成员变量,来操作同一个对象
private Person person;
// 定义一个标识通过改变标识来进行间隔赋值
private boolean isTrue = true;
// 利用构造方法来给成员变量赋值
public SetRunnable() {
super();
}
public SetRunnable(Person person) {
super();
this.person = person;
}
@Override
public void run() {
while (true) {
// 多个线程操作共享数据
// 需要添加锁
// 为了保证两个同步锁的锁对象相同,使用传进来的对象 person
/*
* 赋值线程需要赋值完毕,打印线程才能去打印
* 赋值时,打印线程等待,赋值完毕后,通知打印线程,打印线程才能打印
*
* 同样,打印线程打印完毕,赋值线程才能赋值
* 打印时,赋值线程等待,打印完毕后,通知赋值线程,赋值线程才能赋值
*
* wait 和 notify 使用一个标记来进行切换
* 这个标记赋值线程使用,也要给打印线程使用
* 注意:必须保证使用的是用一个标记,标记声明在 person 类中,即声明在共同对象中
*
*/
synchronized (person) {
// 判断 flag 为 true 时等待,不为 true 时赋值
if (person.flag == true) {
// 进行等待
try {
person.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 间隔赋值
if (isTrue) {
person.name = "张三";
person.gender = "男";
} else {
person.name = "zhangsan";
person.gender = "nv";
}
// 改变标识符
isTrue = !isTrue;
// 修改标记
person.flag = true;
// 唤醒线程
person.notify();
}
}
}
}
// 打印线程
class PrintRunnable implements Runnable {
// 利用成员变量,来操作同一个对象
private Person person;
public PrintRunnable() {
super();
}
public PrintRunnable(Person person) {
super();
this.person = person;
}
@Override
public void run() {
while (true) {
synchronized (person) {
if (person.flag == false) {
try {
person.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// 打印
System.out.println(person);
// 修改标记
person.flag = false;
// 唤醒线程
person.notify();
}
}
}
}
class Person {
public String name;
public String gender;
// 声明标记来切换打印和赋值
public boolean flag = false;
@Override
public String toString() {
return “姓名:” + name + “\n年龄:” + gender;
}
}
/*
* Person1类 姓名 性别
* 开启两个线程
* 一个对Person1对象进行赋值
* 一个对Person1对象进行打印
* 要求
* 一次打印 丁鹏 男
* 一次打印 dingpeng nv
* 间隔输出
*
* 1.先保证要操作的是同一个对象
* 2.要保证数据安全需要使用锁,并且要使用同一把锁
* 3.保证操作的逻辑顺序要对(先赋值,在打印)用 wait 和 notify
*/
public class Demo07 {
public static void main(String[] args) {
// 创建对象(只能使用同一个对象)
Person1 person1 = new Person1();
// 创建线程
SetRunnable1 setRunnable1 = new SetRunnable1(person1);
Thread thread1 = new Thread(setRunnable1);
PrintRunnable1 printRunnable1 = new PrintRunnable1(person1);
Thread thread2 = new Thread(printRunnable1);
thread1.start();
thread2.start();
}
}
// 赋值线程
class SetRunnable1 implements Runnable {
// 利用成员变量,来操作同一个对象
private Person1 person1;
// 定义一个标识通过改变标识来进行间隔赋值
private boolean isTrue = true;
// 利用构造方法来给成员变量赋值
public SetRunnable1() {
super();
}
public SetRunnable1(Person1 person1) {
super();
this.person1 = person1;
}
@Override
public void run() {
while (true) {
/*
* 代码优化
* 把之前上锁的代码封装到类中
* 从同步代码块封装成同步方法
*/
if (isTrue) {
person1.setPerson("张三", "男");
} else {
person1.setPerson("张珊", "女");
}
isTrue = !isTrue;
}
}
}
// 打印线程
class PrintRunnable1 implements Runnable {
// 利用成员变量,来操作同一个对象
private Person1 person1;
public PrintRunnable1() {
super();
}
public PrintRunnable1(Person1 person1) {
super();
this.person1 = person1;
}
@Override
public void run() {
while (true) {
person1.print();
}
}
}
class Person1 {
public String name;
public String gender;
// 声明标记来切换打印和赋值
public boolean flag = false;
// 把操作共享数据的部分写成一个同步的方法
public synchronized void setPerson(String name, String gender) {
// 等待和唤醒
if (flag == true) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.name = name;
this.gender = gender;
// 更改标记
flag = true;
// 唤醒线程
this.notify();
}
// 打印方法
public synchronized void print() {
if (flag == false) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(name + " " + gender);
flag = false;
this.notify();
}
@Override
public String toString() {
return "姓名:" + name + "\n年龄:" + gender;
}
}