10 Java并发编程3-线程间协作总结
来源:互联网 发布:11式榴弹发射器知乎 编辑:程序博客网 时间:2024/05/29 18:54
一 wait()、notify()、notifyAll()
是Object类中的方法。
1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。
2)调用某个对象的wait方法能让当前线程阻塞,并且当前线程必须拥有此对象的锁。
3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象锁的线程,如果有多个线程都在等待这个对象锁,则只能唤醒其中一个线程。
4)调用notifyAll()方法能够唤醒所有正在等待这个对象的锁的线程。
?为什么是Object类中声明的方法,而不是Thread类?
由于每个对象都拥有锁,所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作。
wait方法、notify方法、notifyAll方法必须在同步块或者同步方法中进行。
调用某个线程的wait()方法,相当于让当前线程交出此对象的锁,然后进入等待状态,等待后续再次获得此对象的锁。
notify()方法能够唤醒一个正在等待该对象的锁的线程,一个线程被唤醒不代表立即获取了对象的锁。
package javazongjie;public class Test3 { public static Object object = new Object(); public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); try{ Thread.sleep(2000); }catch (InterruptedException e) { // TODO: handle exception e.printStackTrace(); } thread2.start(); /** * 线程Thread-1调用了object.notify() 线程Thread-1释放了锁 线程Thread-0获取到了锁 */ } static class Thread1 extends Thread{ public void run() { synchronized (object) { try{ object.wait(); }catch (InterruptedException e) { // TODO: handle exception } System.out.println("线程" + Thread.currentThread().getName() + "获取到了锁"); } } } static class Thread2 extends Thread { public void run() { synchronized (object) { object.notify(); System.out.println("线程" + Thread.currentThread().getName() + "调用了object.notify()"); System.out.println("线程" + Thread.currentThread().getName() + "释放了锁"); } } }}
2 Condition
Condition是在java1.5 中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,实现线程间协作更加安全和高效。阻塞队列实际上使用了Condition来模拟线程间协作。
* Condition是个接口,基本的方法是await()和signal()方法;
* Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
* 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用。
Condition中的await()对应Object的wait();
Condition中的signal()对应Object的notify();
Condition中的signalAll()对应Object的notifyAll();
3 生产者-消费者模型的实现
* 使用Object的wait()和notify()实现。
package javazongjie;import java.util.PriorityQueue;public class Test4 { private int queueSize = 3; private PriorityQueue<Integer> queue = new PriorityQueue<>(queueSize); public static void main(String[] args) { Test4 test = new Test4(); Producer producer = test.new Producer(); Consumer consumer = test.new Consumer(); producer.start(); consumer.start(); /** * 向队列中插入一个元素,队列剩余空间:2 向队列中插入一个元素,队列剩余空间:1 向队列中插入一个元素,队列剩余空间:0 队列满,等待有空余空间 从队列取走一个元素,队列剩余2个元素 从队列取走一个元素,队列剩余1个元素 从队列取走一个元素,队列剩余0个元素 队列空,等待数据 //循环输出上述 */ } class Consumer extends Thread { public void run() { consume(); } private void consume() { while(true) { synchronized (queue) { while(queue.size() == 0) { try{ System.out.println("队列空,等待数据"); queue.wait(); }catch (InterruptedException e) { e.printStackTrace(); queue.notify(); } } queue.poll(); queue.notify(); System.out.println("从队列取走一个元素,队列剩余" + queue.size() + "个元素"); } } } } class Producer extends Thread { public void run() { produce(); } private void produce() { while(true) { synchronized (queue) { while(queue.size() == queueSize){ try{ System.out.println("队列满,等待有空余空间"); queue.wait(); }catch (InterruptedException e) { e.printStackTrace(); queue.notify(); } } queue.offer(1); queue.notify(); System.out.println("向队列中插入一个元素,队列剩余空间:" + (queueSize - queue.size())); } } } }}
2 使用Condition实现
package javazongjie;import java.util.PriorityQueue;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Test5 { private int queueSize = 3; private PriorityQueue<Integer> queue = new PriorityQueue<>(queueSize); private Lock lock = new ReentrantLock(); private Condition notFull = lock.newCondition(); private Condition notEmpty = lock.newCondition(); public static void main(String[] args) { Test5 test = new Test5(); Producer producer = test.new Producer(); Consumer consumer = test.new Consumer(); producer.start(); consumer.start(); /** * 向队列中插入一个元素,队列剩余空间:2 从队列取走一个元素,队列剩余0个元素 队列空,等待数据 //循环输出上述 */ } class Consumer extends Thread { public void run() { consume(); } private void consume() { while(true) { lock.lock(); try{ while(queue.size() == 0) { try{ System.out.println("队列空,等待数据"); notEmpty.await(); }catch (InterruptedException e) { e.printStackTrace(); } } queue.poll(); notFull.signal(); System.out.println("从队列取走一个元素,队列剩余" + queue.size() + "个元素"); }finally { lock.unlock(); } } } } class Producer extends Thread { public void run() { produce(); } private void produce() { while(true) { lock.lock(); try{ while(queue.size() == queueSize){ try{ System.out.println("队列满,等待有空余空间"); notFull.await(); }catch (InterruptedException e) { e.printStackTrace(); } } queue.offer(1); notEmpty.signal(); System.out.println("向队列中插入一个元素,队列剩余空间:" + (queueSize - queue.size())); }finally { lock.unlock(); } } } }}
- 10 Java并发编程3-线程间协作总结
- Java并发编程:线程间协作的两种方式
- Java并发编程:Condition实现线程间协作
- Java 并发:线程间通信与协作
- Java 并发:线程间通信与协作
- Java并发之线程间的协作
- 并发编程(三)-线程协作
- JAVA并发编程6_线程协作/生产者-消费者
- Java并发编程实战笔记(5)- 线程协作
- java编程思想笔记-并发之线程协作(一)
- java编程思想笔记-并发之线程协作(二)
- java编程思想笔记-并发之线程协作(三)
- java编程思想笔记-并发之线程协作(四)
- Java并发总结(四):线程的协作
- Java线程:并发协作-死锁
- Java线程:并发协作-死锁
- java并发 --线程的协作
- Java线程:并发协作-死锁
- SecureCRT 配置自动记录日志
- jQuery 遍历 - each() 方法
- cocos2d-x 3.9遇到过的坑
- 问题四十一:怎么用ray tracing画任意圆柱面(generalized cylinder)
- C++中的static关键字的总结
- 10 Java并发编程3-线程间协作总结
- Android创建和删除文件夹和文件
- Python中re模块及正则表达式
- Unity5.4.1与NGUI出现的问题Ignoring menu item NGUI because it is in no submenu!
- 程序员面试金典——解题总结: 9.14Java 14.6实现CircularAray类,支持类似数组的数据结构,这些数据结构可以高效地进行旋转
- ftiasch 两个字符串间隔合并
- CodeForces - 276C Little Girl and Maximum Sum (扫描线)
- TCP快速重传为什么是三次冗余ack,这个三次是怎么定下来的?
- linux新创建用户后的问题