java并发编程实战手册第二章2.8与死锁的演示
来源:互联网 发布:淘宝卖家货到付款骗局 编辑:程序博客网 时间:2024/06/08 17:58
话不多数先上代码
package cn.fans.chapter2.eight;/** * * @author fcs * @date 2015-4-15 * 描述:在锁中使用多个条件(multiple Condition) * 说明: */public class FileMock {Object bul; private String content [] ; //存储文件的内容 private int index; //从文件中读取内容的行号 /** * 使用构造方法生成需要的数据 * @param size * @param length */ public FileMock(int size,int length){ content = new String[size]; for(int i =0;i < size;i++){ StringBuffer buffer = new StringBuffer(length); for(int j =0 ;j< length;j++){ int numb = (int)Math.random() * 255; buffer.append((char)numb); } content[i] = buffer.toString(); } index = 0; } /** * * 作者:fcs * 描述:如果文件有可以处理的数据行则返回true.如果没有可以处理的数据则返回false * 说明: * 返回: * 参数: * 时间:2015-4-15 */ public boolean hasMoreLines(){ return index < content.length; } /** * * 作者:fcs * 描述:返回属性index指定的行内容,并将index自动增加1 * 说明: * 返回: * 参数: * 时间:2015-4-15 */ public String getLine(){ if(this.hasMoreLines()){ System.out.println("mock: "+(content.length - index)); return content[index++]; } return null; } }
package cn.fans.chapter2.eight;import java.util.LinkedList;import java.util.List;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;/** * * @author fcs * @date 2015-4-16 * 描述:缓冲区 * 说明: */public class Buffer {private LinkedList<String> buffer ; // 存放共享数据private int maxsize; //存放buffer的长度private ReentrantLock lock; //用来对修改buffer的代码进行控制。private Condition lines; //控制行数的条件private Condition space; //控制是否有数据的条件boolean pendingLines ; //表示缓冲区是否有数据的条件public Buffer(int maxsize){this.maxsize = maxsize;buffer = new LinkedList<String>(); lock = new ReentrantLock();lines = lock.newCondition();space = lock.newCondition();pendingLines = true;}/** * * 作者:fcs * 描述:将数据插入缓冲区,当缓冲区满的时候,线程等待,当缓冲区有数据的时候唤醒线程 * 说明: * 返回: * 参数: * 时间:2015-4-15 */public void insert(String line){lock.lock(); //获取锁try {while(buffer.size() == maxsize){space.await(); //缓冲区满的时候等待}buffer.offer(line);System.out.printf("%s inserted Line: %d\n",Thread.currentThread().getName(),buffer.size());lines.signalAll() ; //缓冲区有数据的时候唤醒} catch (InterruptedException e) {e.printStackTrace();} finally{lock.unlock(); //释放锁}}/** * * 作者:fcs * 描述:返回缓冲区的第一个字符串,先获取锁,然后检查缓冲区是不是有数据行,如果缓冲区是空的 * 就调用条件lines的await()方法等待缓冲区出现数据。 * 当其他线程调用条件lines的signal()或者signalAll()的时候,该线程唤醒 * 在有数据的时候,get方法获取缓冲区的第一行,并且调用条件space的signalAll()的方法,并且返回这个数据行字符串 * 说明: * 返回: * 参数: * 时间:2015-4-15 */public String get(){String line = null;lock.lock();try {while((buffer.size() == 0) && hasPendingLines()){ //这里当条件是 <span style="font-family: Arial, Helvetica, sans-serif;">buffer.size() == 0) & ||hasPendingLines()就会发生死锁,类型是相互等待对方释放锁。</span>lines.await();}if(hasPendingLines()){line = buffer.poll();System.out.printf("%s LIne readed: %d\n",Thread.currentThread().getName(),buffer.size()); space.signalAll(); }} catch (InterruptedException e) {e.printStackTrace();}finally{lock.unlock();}return line;}/*设置pendingLines的值的,当生产者不再生产新数据行的时候调用该方法*/public void setPendingLines(boolean pendingLines){this.pendingLines = pendingLines;}/*如果有数据行返回true*/public boolean hasPendingLines(){return pendingLines || buffer.size() > 0;}}
package cn.fans.chapter2.eight;import java.util.Random;/** * * @author fcs * @date 2015-4-15 * 描述:消费者线程 * 说明: */public class Consumer implements Runnable {private Buffer buffer;public Consumer(Buffer buffer) {super();this.buffer = buffer;}@Overridepublic void run() {while(buffer.hasPendingLines()){String line = buffer.get();processLine(line);}}//休眠10毫秒,模拟数据处理public void processLine(String line){Random random = new Random();try {Thread.sleep(random.nextInt(100));} catch (InterruptedException e) {e.printStackTrace();}}}
package cn.fans.chapter2.eight;/** * * @author fcs * @date 2015-4-15 * 描述:生产者线程 * 说明: */public class Producer implements Runnable{private FileMock fileMock;private Buffer buffer;public Producer(FileMock fileMock, Buffer buffer) {super();this.fileMock = fileMock;this.buffer = buffer;}/** * 用来读取文件中的所有行,并且使用insert方法将数据插入到缓冲区中 * 读完数据后设置pendingLines方法通知缓冲区停止生产更多的行。 */@Overridepublic void run() {buffer.setPendingLines(true);while(fileMock.hasMoreLines()){String line = fileMock.getLine();buffer.insert(line);}buffer.setPendingLines(false);}}
package cn.fans.chapter2.eight;public class Main {public static void main(String[] args) {FileMock fileMock = new FileMock(100, 10);Buffer buffer = new Buffer(20);Producer producer = new Producer(fileMock, buffer);Thread pthread = new Thread(producer,"producer");Consumer consumer [] = new Consumer[3];Thread cthread [] = new Thread[3];for(int i =0;i< 3;i++){consumer[i] = new Consumer(buffer);cthread[i] = new Thread(consumer[i]);}pthread.start();for(int i =0;i< 3;i++){cthread[i].start();}}}
2.8在锁中使用多个条件(Multiple Condition) ---->生产者--消费者问题,使用锁和Condition条件实现,加入数据缓冲区
1.一个锁可能关联一个或者多个条件,这些条件通过Condition接口声明,目的是允许线程获取锁并且查看等待的某个条件是否满足,如果不满足
就挂起直到某个线程唤醒它们。
2.Condition接口提供了挂起线程和唤醒线程的机制。
3.本节使用一个数据缓冲区当做生产者生产数据的容器,消费者从该缓冲区获得数据。
4.与锁绑定的所有条件对象都是通过Lock接口声明的newCondition方法创建,返回一个Condition对象。
5.在使用条件的时候,必须获取该条件绑定的锁,带条件的代码必须在调用Lock对象的lock()方法和unlock()方法之间。
6.Condition接口提供了多个方法用来休眠和唤醒线程。
线程调用await()方法时,该线程自动释放这个条件绑定的锁,其他某个线程才可以获取这个锁并且执行相同的操作,或者执行这个锁保护的另一个临界区代码
7.必须在while循环中调用await()方法,在条件成立之前不能离开这个循环,当条件不成立时再次调用该方法。
8.signal()方法用来唤醒在某个条件成立的时候在等待锁的线程,并且该方法与await()方法是成对出现的。
9.如果调用了一个条件的await()方法,却没有调用signal()方法这个线程将永远休眠。
10.在本案例中修改while循环的条件将导致死锁。
2.9Condition条件的方法说明
1.await(long time,TimeUnit unit):该方法将等待一定的时间直到发生以下情况之前,线程一直处于休眠状态
1.其他某个线程中断当前线程。
2.其他某个线程调用了将当前线程挂起的条件的signal()方法或者signalAll()方法,就是提前唤醒。
3.指定的等待时间已经过去,自己自动醒来。
4.通过TimeUnit类的常量指定等待的时间。
2.awaitUninterruptibly():是不可中断的。这个线程将休眠直到其他某个线程调用将它挂起的条件的signal()或者signalAll()方法
3.awaitUnit(Date date)调用该方法的线程休眠和唤醒的时机与方法1相同。
0 0
- java并发编程实战手册第二章2.8与死锁的演示
- java并发编程实战手册第二章笔记
- Java并发编程实战--死锁
- java并发编程实战手册第二章使用读写锁实现同步数据访问
- Java并发编程实战 第二章
- 2.Java并发编程实战--第二章
- Java并发编程实战--协作对象间的死锁与开放调用
- java并发编程实战笔记-死锁
- java并发编程—— 七 Thread理解与死锁分析(哲学家进餐演示)
- java并发编程实战手册第三章---CountDownLatch使用
- Java 7并发编程实战手册
- java并发编程实战手册第一章
- Java 7 并发编程实战手册目录
- JAVA 7并发编程实战手册
- 关于《Java并发编程实战》 -- 第二部分的阅读笔记
- 《Java并发编程实战》第二章 线程安全性 读书笔记
- Java并发编程实战 第二,三,四章
- java 并发编程实战 第二天
- javascript里function函数的用法
- 模拟收音机放新闻电池电量减少的程序
- MYSQL 使用DBI
- FJNU摸底赛_acdream1680(水题)
- Django项目实践3 - Django模型(view-数据库)
- java并发编程实战手册第二章2.8与死锁的演示
- 黑马程序员——学习日记
- Objective-C中,当self作为当前类时需要注意的细节
- C#中的垃圾回收机制
- HQL多对多条件查询
- Unbound classpath container: 'JRE System Library
- jQuery 遍历 - closest() 方法
- 100题解题报告
- UI delegate设计模式