Java学习笔记46(多线程三:线程之间的通信)
2018-01-20 14:31
525 查看
多个线程在处理同一个资源,但是线程的任务却不相同,通过一定的手段使各个线程能有效地利用资源,
这种手段即:等待唤醒机制,又称作线程之间的通信
涉及到的方法:wait(),notify()
示例:
两个线程一个输入,一个输出
输入线程:
输出线程:
测试类:
运行后却发现输出的都是null...null
因为输入线程和输出线程中创建的Resource对象使不同的
解决null问题:
运行后又发现了另一个问题:
输出中含有:张三...女或者李四...男,性别出错
发生原因:
赋值完张三和男后,继续赋值李四和女,这时候还未还得及赋值女,就进入了输出线程,这时候就会输出李四...男
于是想到加上同步:
然而问题并没有解决:
原因:
这里的同步失去了作用,用到的不是一个锁
解决办法:
使用一个共同的锁即可
这时候就是正常的输出了
但是还是存在一个问题,我们希望的是张三和李四交错出现,一个张三一个李四,现在依然是随机出现的,大片的张三或李四
解决办法:
先让input线程赋值,然后让output线程输出,并且让输入线程等待,不允许再赋值李四,等待输出张三结束后,再允许李四赋值,依次下去
输入线程也需要同样的方式,输出完后要等待
这时候就需要用到等待唤醒机制:
输入:赋值后,执行方法wait()永远等待
输出:打印后,再输出等待之前,唤醒输入notify(),自己再wait()永远等待
输入:被唤醒后,重新赋值,必须notify()唤醒输出的线程,自己再wait()等待
依次循环下去
代码实现:
这时候就是张三李四交错输出了
完成
这种手段即:等待唤醒机制,又称作线程之间的通信
涉及到的方法:wait(),notify()
示例:
两个线程一个输入,一个输出
package demo; public class Resource { public String name; public String sex; }
输入线程:
package demo; public class Input implements Runnable { private Resource r = new Resource(); public void run() { int i = 0; while (true) { if (i % 2 == 0) { r.name = "张三"; r.sex = "男"; } else { r.name = "李四"; r.sex = "女"; } i++; } } }
输出线程:
package demo; public class Output implements Runnable { private Resource r = new Resource(); public void run(){ while (true) { System.out.println(r.name+"..."+r.sex); } } }
测试类:
package demo; public class ThreadDemo { public static void main(String[] args) { Input in = new Input(); Output out = new Output(); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start(); tout.start(); } }
运行后却发现输出的都是null...null
因为输入线程和输出线程中创建的Resource对象使不同的
解决null问题:
package demo; public class Input implements Runnable { private Resource r; public Input(Resource r){ this.r = r; } public void run() { int i = 0; while (true) { if (i % 2 == 0) { r.name = "张三"; r.sex = "男"; } else { r.name = "李四"; r.sex = "女"; } i++; } } }
package demo; public class Output implements Runnable { private Resource r; public Output(Resource r){ this.r = r; } public void run(){ while (true) { System.out.println(r.name+"..."+r.sex); } } }
package demo; public class ThreadDemo { public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r); Output out = new Output(r); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start(); tout.start(); } }
运行后又发现了另一个问题:
输出中含有:张三...女或者李四...男,性别出错
发生原因:
赋值完张三和男后,继续赋值李四和女,这时候还未还得及赋值女,就进入了输出线程,这时候就会输出李四...男
于是想到加上同步:
public void run() { int i = 0; while (true) { synchronized (this) { if (i % 2 == 0) { r.name = "张三"; r.sex = "男"; } else { r.name = "李四"; r.sex = "女"; } i++; } } }
public void run() { while (true) { synchronized (this) { System.out.println(r.name + "..." + r.sex); } } }
然而问题并没有解决:
原因:
这里的同步失去了作用,用到的不是一个锁
解决办法:
使用一个共同的锁即可
public void run() { int i = 0; while (true) { synchronized (r) { if (i % 2 == 0) { r.name = "张三"; r.sex = "男"; } else { r.name = "李四"; r.sex = "女"; } i++; } } }
public void run() { while (true) { synchronized (r) { System.out.println(r.name + "..." + r.sex); } } }
这时候就是正常的输出了
但是还是存在一个问题,我们希望的是张三和李四交错出现,一个张三一个李四,现在依然是随机出现的,大片的张三或李四
解决办法:
先让input线程赋值,然后让output线程输出,并且让输入线程等待,不允许再赋值李四,等待输出张三结束后,再允许李四赋值,依次下去
输入线程也需要同样的方式,输出完后要等待
这时候就需要用到等待唤醒机制:
输入:赋值后,执行方法wait()永远等待
输出:打印后,再输出等待之前,唤醒输入notify(),自己再wait()永远等待
输入:被唤醒后,重新赋值,必须notify()唤醒输出的线程,自己再wait()等待
依次循环下去
代码实现:
package demo; public class Resource { public String name; public String sex; public boolean flag = false; }
package demo; public class Input implements Runnable { private Resource r; public Input(Resource r) { this.r = r; } public void run() { int i = 0; while (true) { synchronized (r) { if (r.flag) { try { r.wait(); } catch (Exception e) { } } if (i % 2 == 0) { r.name = "张三"; r.sex = "男"; } else { r.name = "李四"; r.sex = "女"; } r.flag = true; r.notify(); } i++; } } }
package demo; public class Output implements Runnable { private Resource r; public Output(Resource r) { this.r = r; } public void run() { while (true) { synchronized (r) { if (!r.flag) { try { r.wait(); } catch (Exception e) { } } System.out.println(r.name + "..." + r.sex); r.flag = false; r.notify(); } } } }
package demo; public class ThreadDemo { public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r); Output out = new Output(r); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start(); tout.start(); } }
这时候就是张三李四交错输出了
完成
相关文章推荐
- 学习java多线程的笔记3-使用BlockingQueue阻塞队列来模拟两个线程之间的通信
- Java线程学习笔记之线程协作(通信)
- 黑马程序员—11—java基础:有关线程通信的学习笔记和学习心得体会
- Java学习笔记之线程间的通信
- 线程之间的通信socketpair【学习笔记】【原创】
- JAVA基础学习(十二)--多线程一线程之间的通信
- 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题
- Java并发学习笔记(13)线程之间的协作(Object.wait(),notifu(),notifyAll() Thread.join())
- Java学习笔记81. 线程间的通信 —— wait( ),notify( ),和 notifyAll( )
- java个人学习笔记18(多线程之间通信+等待唤醒机制)
- 【Java学习笔记】60:客户端PC-后端程序服务器-数据库服务器之间的通信demo
- java学习之路——线程3(线程之间的通信)
- Android(java)学习笔记70:同步中的死锁问题以及线程通信问题
- Java学习笔记(线程间通信)
- java 多线程学习笔记3-单例设计 线程间通信 互斥锁
- (46)Java学习笔记——多线程 / 线程的生命周期
- java学习——如何实现线程之间的通信 ,Condition 的使用
- JAVA学习笔记(1)_____模拟线程通信之生产者消费者问题
- (48)Java学习笔记——多线程 / 线程间通信 / 线程组 / 线程池 /
- Java学习笔记45:Java 线程与主线程之间的变量关系