线程间通信问题学习
来源:互联网 发布:利用excel制作软件 编辑:程序博客网 时间:2024/05/16 04:48
线程间通信涉及的方法
多个线程在处理统一资源,但是任务却不同,这时候就需要线程间通信。
等待/唤醒机制涉及的方法:
1. wait():让线程处于冻结状态,被wait的线程会被存储到线程池中。
2. notify():唤醒线程池中的一个线程(任何一个都有可能)。
3. notifyAll():唤醒线程池中的所有线程。
P.S.
1、这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法。
2、必须要明确到底操作的是哪个锁上的线程!
3、wait和sleep区别?
1)wait可以指定时间也可以不指定。sleep必须指定时间。
2)在同步中时,对CPU的执行权和锁的处理不同。
wait:释放执行权,释放锁。
sleep:释放执行权,不释放锁。
为什么操作线程的方法wait、notify、notifyAll定义在了object类中,因为这些方法是监视器的方法,监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方式一定在object类中。
生产者-消费者问题:
等待/唤醒机制涉及的方法:
1. wait():让线程处于冻结状态,被wait的线程会被存储到线程池中。
2. notify():唤醒线程池中的一个线程(任何一个都有可能)。
3. notifyAll():唤醒线程池中的所有线程。
P.S.
1、这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法。
2、必须要明确到底操作的是哪个锁上的线程!
3、wait和sleep区别?
1)wait可以指定时间也可以不指定。sleep必须指定时间。
2)在同步中时,对CPU的执行权和锁的处理不同。
wait:释放执行权,释放锁。
sleep:释放执行权,不释放锁。
为什么操作线程的方法wait、notify、notifyAll定义在了object类中,因为这些方法是监视器的方法,监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方式一定在object类中。
生产者-消费者问题:
class Resource{ private String name ; private String sex ; private boolean flag = false; public synchronized void set(String name,String sex){ if(flag ) try{ this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } this.name = name; this.sex = sex; flag = true ; this.notify(); } public synchronized void out(){ if(!flag ) try{ this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } System. out.println(name + "..." + sex); flag = false ; this.notify(); } }//输入class Input implements Runnable{ Resource r; Input(Resource r){ this.r = r; } public void run(){ int x = 0; while(true ){ if(x == 0){ r.set( "mike","男" ); } else{ r.set( "lili","女" ); } x = (x + 1)%2; } }}//输出class Output implements Runnable{ Resource r; Output(Resource r){ this.r = r; } public void run(){ while(true ){ r.out(); } }}class ResourceDemo { public static void main(String[] args){ //创建资源 Resource r = new Resource(); //创建任务 Input in = new Input(r); Output out = new Output(r); //创建线程,执行路径 Thread t1 = new Thread(in); Thread t2 = new Thread(out); //开启线程 t1.start(); t2.start(); }}
多生产者-多消费者问题:
class Resource{ private String name ; private int count = 1; private boolean flag = false; public synchronized void set(String name){ if(flag ) try{ wait(); } catch(InterruptedException e){ e.printStackTrace(); } this.name = name + count; count++; System.out.println(Thread.currentThread().getName() + "...生产者..." + this. name); flag = true ; notify(); } public synchronized void out(){ if(!flag ) try{ wait(); } catch(InterruptedException e){ e.printStackTrace(); } flag = false ; notify(); System.out.println(Thread.currentThread().getName() + "...消费者..." + this. name); }}class Producer implements Runnable{ private Resource r ; Producer(Resource r){ this.r = r; } public void run(){ while(true ){ r.set( "烤鸭"); } }}class Consumer implements Runnable{ private Resource r ; Consumer(Resource r){ this.r = r; } public void run(){ while(true ){ r.out(); } }} class ProducerConsumerDemo { public static void main(String[] args){ Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t0 = new Thread(pro); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); Thread t3 = new Thread(con); t0.start(); t1.start(); t2.start(); t3.start(); }}
原因分析:
得到以上结果的过程分析如下:
1. 线程Thread-0获取到CPU执行权及锁,生产了烤鸭3298,将flag设置为true。然后,Thread-0又重新获取到CPU执行权,由于flag为true,故执行wait方法,阻塞。Thread-1接着获取到CPU执行权,由于flag为true,故执行wait方法,也阻塞。
2. 线程Thread-3获取到CPU执行权及锁,消费了烤鸭3298,将flag设置为false。然后,线程Thread-0被唤醒,但是并没有获取到锁,而是线程Thread-3接着获取到CPU执行权及锁,然而此时flag为false,所以Thread-3阻塞。下面线程Thread-2接着获取到CPU执行权及锁,然而此时flag为false,所以Thread-2也阻塞。
3. 线程Thread-0获取到CPU执行权及锁,不需要if语句判断,直接生产烤鸭3299,然后又唤醒线程Thread-1获取到CPU执行权及锁,不需要if语句判断,直接生产烤鸭3300。从而造成了烤鸭3299还没有被消费,就直接生产了烤鸭3300的情况。
由于if判断标记,只有一次,会导致不该运行的线程运行了,出现了数据错误的情况。故修改成while判断标记,线程获取CPU执行权及锁后,将重新判断是否具备运行条件。
notify方法只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。notifyAll解决了本方线程一定会唤醒对方线程的问题。
P.S.
while判断标记+notify会导致死锁的示例:
如果将上面的代码中的if判断标记修改成wile判断标记,就会出现死锁的现象,前2步与原来是一致的。第3步如下:
3. 线程Thread-0获取到CPU执行权及锁,通过了while语句判断,直接生产烤鸭3299,将flag设置为true。然后又唤醒线程Thread-1获取到CPU执行权及锁,没有通过while语句判断,阻塞。线程Thread-0又获取到CPU执行权及锁,通不过while语句判断,也阻塞,此时Thread-0、1、2、3都阻塞,故死锁。
0 0
- 线程间通信问题学习
- 线程间通信问题学习
- 线程间的通信问题
- JAVA线程间通信问题
- JAVA线程间通信问题
- 线程间通信的问题
- java学习--线程间通信
- 线程间通信学习笔记
- 线程及 进程间的通信问题!
- 线程间通信问题的解决
- 线程间通信,生产者消费者问题!
- Java——线程间通信问题
- 线程间通信之生产者消费者问题
- 线程和 进程间的通信问题
- Android的线程间的通信问题
- 线程间通信的问题:使用AsyncTask:
- 线程间通信(生产者消费者问题)
- Java实现--线程间通信问题案例
- margin:0 auto 与 text-align:center 的区别
- 自我总结 数据分析师必读
- Dialog显示View报错的问题
- 在Xcode中使用Git进行源码版本控制
- hdu2473 Junk-Mail Filter 并查集+删除节点+路径压缩
- 线程间通信问题学习
- Linux shell知多少
- java向C++传图片
- UVA-10474 Where is the Marble?
- Apache通用日志工具commons-logging和Log4j使用总结
- Redhat6.4下MySQL5.6.26二进制版安装配置
- taobao
- iOS开发范例实战宝典(进阶篇)——互动出版网
- Atlassian Crowd安装