package cn.sdut.threadclass;
/*
*
* 多线程访问同一资源第三步 : 线程设置 以及线程 线程打印 用synchronized
* 两个线程:(注意这里是两个线程 ,多个线程 只需要把 notify 改成 notifyAll)
* 一个线程输入
* 另一个线程打印
* 实现 输入一个 打印一个的效果
*/
class Person1 { // 这里是共同的资源 而且设置和输出数据都在里面进行 对数据进行操作时 需要进行 同步
private String name;
private char sex;
private boolean flag = false;// 与上一篇不同的是 我们这里添加了一个 flag 用来判断是应该 输入 还是 打印
public synchronized void setAttribute(String name, char sex) {
while (flag) { // 如果 flag 为 true就说明已经输入了一条数据了 ,就让准备再塞入数据的线程休眠 等待打印完唤醒它 使用while判断更加安全
try {
this.wait(); // 线程wait()后 会自动放弃锁 而 sleep()不会放弃锁 并且 一定要使用相同的锁对象 同步非静态方法的锁是this 同步静态方法的锁是类的class文件
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name;
this.sex = sex;
flag = true;//设置 为true 表示 数据已经设置了 上面判断是否等待的时候就会判断到
notify(); // notify 是随机唤醒一个线程 我们这里只有两个线程 那么肯定是唤醒另一个打印线程 notifyAll是唤醒所有线程
// notifyAll();
}
public synchronized void printAttribute() { // 同步 方法
while (!flag) { // 如果 flag 为false就说明已经打印了一条数据了 ,就让准备再打印数据的线程休眠 等待输入完唤醒它
try {
this.wait(); // 线程wait()后 会自动放弃锁 而 sleep()不会放弃锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.name + " " + this.sex);
flag = false;
notify();
// notifyAll();
}
}
// 实现 Runnable 接口 调用方法设置数据
class In implements Runnable {
private Person1 person = null;
public In(Person1 person) {
this.person = person;
}
@Override
public void run() {
for (int i = 0; i < 500; i++) {
if (i % 2 == 0) {
person.setAttribute("柯南", '男');
} else {
person.setAttribute("少司命", '女');
}
}
}
}
//实现 Runnable 接口 调用方法打印数据
class Out implements Runnable {
private Person1 person = null;
public Out(Person1 person) {
this.person = person;
}
@Override
public void run() {
for (int i = 0; i < 500; i++) {
person.printAttribute();
}
}
}
public class ThreadDemo03 {
public static void main(String[] args) {
Person1 person = new Person1();// 建立共享
In in = new In(person);
Out out = new Out(person);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
// Thread t3 = new Thread(in);
// Thread t4 = new Thread(out);
t1.start();
t2.start();
// t3.start();
// t4.start();
}
}