/*
* 线程间通信
* 本例子编码分为3部分
* 代码后面是无注释表示第一次编码
* 代码后面是//2表示第二次编码
* 代码后面是//3表示第三次编码
*/
/*
* 两个线程的共享资源
* 单例设计模式可以确定
* 两个线程操作一个资源
*/
class Res {
String name;
String sex;
boolean state = false; //3
private Res() {
}
private static final Res r = new Res();
public static Res getInstance() {
return r;
}
}
/*
* 资源输入的线程 如果没有同步的话,
* 很有可能 输入资源先存入了一个 [pinyin] [nan]
* 当输入资源再次输入 [汉字] 这个时候
* 输出资源获得了执行权,往外读数据
* 那么输出资源读到的就是[汉字][nan]
* 这个时候读到的资源就是错误的
* 通过线程同步的话解决了这个问题之后
* 会发现虽然同步了,但是有的时候
* input狂装output狂取,正常情况下应该是
* input装一个,output取一个,所以要
* 用到线程的等待唤醒机制
* 可以在共享资源中加入一个状态位的判断
* false就是没有存入,true就是没有取出
* 先说input
* 默认是false,存入之后改为true,然后
* 这个input的线程就不要再执行了,
* 再执行状态位也是false,占用资源,直接wait();
* 当状态位是true的时候表示output要取了,
* 这时候notify();唤醒wait();的线程
* output相反
* 线程运行的时候会在内存中创建一个线程池
* 线程wait();的时候,会等待在线程池中,
* notify();会唤醒第一个wait();在线程池中的线程
*
* 注意!wait();和notify();方法在使用时
* 明确指出:
* 当前线程必须拥有此对象监视器!!!
* 监视器就是锁定的对象,
* 所以要用该对象调用这两个方法,这里要特别注意
* 可能同步嵌套!
* 要明确自己应该用哪个锁定的对象去调用方法
*/
class Input implements Runnable {
Res s = Res.getInstance();
@Override
public void run() {
boolean flag = true;
while (true) {
synchronized (s) { //2
if(s.state) { //3
try { //3
s.wait(); //3
} catch (InterruptedException e) { //3
e.printStackTrace(); //3
} //3
} //3
if (flag) {
s.name = "pinyin";
s.sex = "nan";
flag = false;
} else {
s.name = "汉字";
s.sex = "女";
flag = true;
}
s.state = true; //3
s.notify(); //3
} //2
}
}
}
/*
* 资源输出的线程
*/
class Output implements Runnable {
Res s = Res.getInstance();
@Override
public void run() {
while (true) {
synchronized(s) { //2
if(!s.state) { //3
try { //3
s.wait(); //3
} catch (InterruptedException e) { //3
e.printStackTrace(); //3
} //3
} //3
System.out.println(s.name + "....." + s.sex);
s.state = false; //3
s.notify(); //3
} //2
}
}
}
public class Thread_InputOutput {
public static void main(String[] args) {
Input in = new Input();
Output out = new Output();
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
java线程间通信_线程同步_等待唤醒机制
最新推荐文章于 2022-12-28 09:55:28 发布