Java学习笔记46(多线程三:线程之间的通信)
2018-06-18 03:46:09来源:未知 阅读 ()
多个线程在处理同一个资源,但是线程的任务却不相同,通过一定的手段使各个线程能有效地利用资源,
这种手段即:等待唤醒机制,又称作线程之间的通信
涉及到的方法: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(); } }
这时候就是张三李四交错输出了
完成
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- 2020年java就业前景 2020-06-11
- 04.Java基础语法 2020-06-11
- Java--反射(框架设计的灵魂)案例 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash