第二章 Basic Thread Synchronization (基础线程同步) 【下】
来源:互联网 发布:mac os sierra降级 编辑:程序博客网 时间:2024/06/08 04:07
涉及的内容
日志:
日志:部分日志
- 同步一个方法
- 同步类中分配一个独立属性
- 在同步代码中使用条件
- 使用Lock锁定代码块
- 同步数据的读写锁
- 修改Lock公平模式
- 在Lock中使用多条件
1、同步数据的读写锁
ReadWriteLock接口 和 ReentrantReadWriteLock类
例子:使用ReadWriteLock接口获取一个存储两个产品的价格
package com.jack;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;public class PricesInfo {private double price1;private double price2;private ReadWriteLock lock;public PricesInfo() {super();this.price1 = 1.0;this.price2 = 2.0;lock = new ReentrantReadWriteLock();}public double getPrice1(){lock.readLock().lock();double value = price1;lock.readLock().unlock();return value;}public double getPrice2(){lock.readLock().lock();double value = price2;lock.readLock().unlock();return value;}public void setPrices(double price1, double price2){lock.writeLock().lock();this.price1 = price1;this.price2= price2;lock.writeLock().unlock();}}
package com.jack;public class Reader implements Runnable {private PricesInfo pricesInfo;public Reader(PricesInfo pricesInfo) {super();this.pricesInfo = pricesInfo;}@Overridepublic void run() {for (int i=0; i< 10; i++){System.out.printf("%s:价格1 : %f\n", Thread.currentThread().getName(),pricesInfo.getPrice1());System.out.printf("%s:价格2:%f\n", Thread.currentThread().getName(),pricesInfo.getPrice2());}}}
package com.jack;public class Writer implements Runnable{private PricesInfo pricesInfo;public Writer(PricesInfo pricesInfo) {super();this.pricesInfo = pricesInfo;}@Overridepublic void run() {for(int i=0; i<3; i++){System.out.printf("写:尝试修改价格.\n");pricesInfo.setPrices(Math.random()*10, Math.random()*8);System.out.printf("写:价格已经修改了.\n");try{Thread.sleep(2);} catch(InterruptedException e){e.printStackTrace();}}}}
package com.jack;public class Main {public static void main(String[] args){PricesInfo pricesInfo = new PricesInfo();Reader readers[] = new Reader[5];Thread threadsReader[] = new Thread[5];for (int i=0; i<5; i++){readers[i] = new Reader(pricesInfo);threadsReader[i] = new Thread(readers[i]);}Writer writer = new Writer(pricesInfo);Thread threadWriter = new Thread(writer);for(int i=0; i<5; i++){threadsReader[i].start();}threadWriter.start();}}
总结:
- 1、创建5个读线程和一个写线程,
- 2、创建一个new ReentrantReadWriteLock() 读写锁。
- 3、对于需要锁定部分进行锁住,这时候只有一个线程可以执行。最后释放锁
- 4、写锁并不会限制读,所以出现脏读。
2、修改Lock公平模式
non-fair mode(非公平模式) : false (选择执行线程没有规则)
fair mode(公平模式) :true (选择规则等待时间最长)
例子:了解公平模式和非公平模式
package com.jack;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class PrintQueue {private final Lock queueLock = new ReentrantLock(true);public void printJob(Object document){queueLock.lock();try {Long duration = (long) (Math.random()*10000);System.out.printf(Thread.currentThread().getName()+ ":打印队列:打印一个工作持续时间 %s ",(duration/1000)+ " seconds \n");Thread.sleep(duration);} catch (InterruptedException e){e.printStackTrace();}finally{queueLock.unlock();}queueLock.lock();try {Long duration = (long) (Math.random()*10000);System.out.printf(Thread.currentThread().getName()+ ":打印队列:打印一个工作持续时间 %s ",(duration/1000)+ " seconds \n");Thread.sleep(duration);} catch (InterruptedException e){e.printStackTrace();}finally{queueLock.unlock();}}}
package com.jack;public class Main {public static void main(String[] args){PrintQueue printQueue = new PrintQueue(); Thread thread[] = new Thread[10]; for (int i=0; i<10; i++){ thread[i]= new Thread(new Job(printQueue), "线程 " + i); } for(int i=0; i<10; i++){ thread[i].start(); try{ Thread.sleep(100); } catch (InterruptedException e){ e.printStackTrace(); } } }}
日志:
线程 0:去打印一个文档线程 0:打印队列:打印一个工作持续时间 7 seconds 线程 1:去打印一个文档线程 2:去打印一个文档线程 3:去打印一个文档线程 4:去打印一个文档线程 5:去打印一个文档线程 6:去打印一个文档线程 7:去打印一个文档线程 8:去打印一个文档线程 9:去打印一个文档线程 1:打印队列:打印一个工作持续时间 9 seconds 线程 2:打印队列:打印一个工作持续时间 4 seconds 线程 3:打印队列:打印一个工作持续时间 9 seconds 线程 4:打印队列:打印一个工作持续时间 8 seconds 线程 5:打印队列:打印一个工作持续时间 2 seconds 线程 6:打印队列:打印一个工作持续时间 9 seconds 线程 7:打印队列:打印一个工作持续时间 4 seconds 线程 8:打印队列:打印一个工作持续时间 5 seconds 线程 9:打印队列:打印一个工作持续时间 3 seconds 线程 0:打印队列:打印一个工作持续时间 4 seconds 线程 0: 这个文档已经打印了线程 1:打印队列:打印一个工作持续时间 6 seconds 线程 1: 这个文档已经打印了线程 2:打印队列:打印一个工作持续时间 3 seconds 线程 2: 这个文档已经打印了线程 3:打印队列:打印一个工作持续时间 6 seconds 线程 3: 这个文档已经打印了线程 4:打印队列:打印一个工作持续时间 5 seconds 线程 4: 这个文档已经打印了线程 5:打印队列:打印一个工作持续时间 7 seconds 线程 5: 这个文档已经打印了线程 6:打印队列:打印一个工作持续时间 4 seconds 线程 6: 这个文档已经打印了线程 7:打印队列:打印一个工作持续时间 3 seconds 线程 7: 这个文档已经打印了线程 8:打印队列:打印一个工作持续时间 4 seconds 线程 8: 这个文档已经打印了线程 9:打印队列:打印一个工作持续时间 7 seconds 线程 9: 这个文档已经打印了
- 1、公平模式下,当线程0放弃一个锁的时候,线程1获取线程0放弃的锁,线程0继续等待(这个类似,打牌一样,轮着出牌,线程0要等到下一轮)
- 2、非公平模式就是全凭CPU大人指派了。
- 3、简单来说,公平:民主国家,非公平:独裁国家
3、在Lock中使用多条件(Condtion接口)
唤醒线程的boolean值
生产者-消费者
package com.jack;public class FileMock {private String content[];private int index;public FileMock(int size, int length){content = new String[size];for(int i=0; i<size; i++){StringBuilder buffer = new StringBuilder(length);for(int j=0; j<length; j++){int indice = (int)Math.random()*255;buffer.append((char)indice);}content[i] = buffer.toString();}index = 0;}public boolean hashMoreLines(){return index < content.length;}public String getLine(){if(this.hashMoreLines()) {System.out.printf("Mock: ", (content.length-index));return content[index++];}return null;}}
package com.jack;import java.util.LinkedList;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;public class Buffer {private LinkedList<String> buffer;private int maxSize;private ReentrantLock lock;private Condition lines;private Condition space;//判断当前行是否在buffer中private boolean pendingLines;public Buffer(int maxSize) {this.maxSize = maxSize;buffer = new LinkedList<>();lock = new ReentrantLock();lines = lock.newCondition();space = lock.newCondition();pendingLines = true;}/** * 插入一行 * @param line */public void insert(String line){lock.lock();try{while(buffer.size() == maxSize){space.await();}buffer.offer(line);System.out.printf("%s: 插入行: %d\n", Thread.currentThread().getName(), buffer.size());//唤醒所有线程lines.signalAll();} catch (InterruptedException e){e.printStackTrace();}finally {lock.unlock();}}/** * 获取一行 * @return */public String get(){String line = null;lock.lock();try{while ((buffer.size()==0) && (hasPendingLines())){lines.await();}if(hasPendingLines()){line = buffer.poll();System.out.printf("%s :行数已经读取:%d\n", Thread.currentThread().getName(), buffer.size());space.signalAll();}}catch (InterruptedException e){e.printStackTrace();}finally{lock.unlock();}return line;}public void setPendingLines(boolean pendingLines){this.pendingLines = pendingLines;}public boolean hasPendingLines(){return pendingLines||buffer.size() >0;}}
package com.jack;public class Producer implements Runnable{private FileMock mock;private Buffer buffer;public Producer(FileMock mock, Buffer buffer) {super();this.mock = mock;this.buffer = buffer;}@Overridepublic void run() {buffer.setPendingLines(true);while (mock.hashMoreLines()){String line = mock.getLine();buffer.insert(line);}buffer.setPendingLines(false);}}
package com.jack;import java.util.Random;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);}}private void processLine(String line) {try{Random random = new Random();Thread.sleep(random.nextInt(100));} catch (InterruptedException e){e.printStackTrace();}}}
package com.jack;public class Main {public static void main(String[] args){FileMock mock = new FileMock(100, 10);Buffer buffer = new Buffer(20);Producer producer = new Producer(mock, buffer);Thread threadProducer = new Thread(producer, "Producer");Consumer consumers[] = new Consumer[3];Thread threadConsumers[] = new Thread[3];for (int i=0; i<3; i++){consumers[i] = new Consumer(buffer);threadConsumers[i] = new Thread(consumers[i], "Consumer "+i);}threadProducer.start();for(int i=0; i<3; i++){threadConsumers[i].start();}}}
日志:部分日志
MOck: Producer: 插入行: 1MOck: Producer: 插入行: 2MOck: Consumer 0 :行数已经读取:1Consumer 1 :行数已经读取:0Producer: 插入行: 1MOck: Producer: 插入行: 2MOck: Consumer 2 :行数已经读取:1Producer: 插入行: 2MOck: Producer: 插入行: 3MOck: Producer: 插入行: 4MOck: Producer: 插入行: 5MOck: Producer: 插入行: 6MOck: Producer: 插入行: 7MOck: Producer: 插入行: 8MOck: Producer: 插入行: 9MOck: Producer: 插入行: 10MOck: Producer: 插入行: 11MOck: Producer: 插入行: 12MOck: Producer: 插入行: 13MOck: Producer: 插入行: 14MOck: Producer: 插入行: 15MOck: Producer: 插入行: 16MOck: Producer: 插入行: 17MOck: Producer: 插入行: 18MOck: Producer: 插入行: 19MOck: Consumer 1 :行数已经读取:18Producer: 插入行: 19MOck: Producer: 插入行: 20MOck: Consumer 1 :行数已经读取:19Producer: 插入行: 20MOck: Consumer 1 :行数已经读取:19Producer: 插入行: 20MOck: Consumer 0 :行数已经读取:19Producer: 插入行: 20MOck: Consumer 0 :行数已经读取:19
总结:
- 1、采用space和lines都是两个条件来影响生产还是消费。
- 2、这里用了Condition的sign()和signAll()方法来唤醒对方
- 3、FileMock模拟生产文件。
- 4、pendingLines判断buffer还有未读取的行。true表示有未读行。(表示还在生产)
第二章完。。。。。。。
阅读全文
0 0
- 第二章 Basic Thread Synchronization (基础线程同步) 【下】
- 第二章 Basic Thread Synchronization (基础线程同步) 【上】
- 第三章 Thread Synchronization Utilities(线程同步工具类)【下】
- 第三章 Thread Synchronization Utilities(线程同步工具类)【上】
- 第二章线程同步基础
- ACE线程安全与同步(Thread Safety and Synchronization)
- ACE线程安全与同步(Thread Safety and Synchronization)
- Java线程基础(二):Synchronization
- Java学习之线程同步(Synchronization)
- 第二部分:线程同步基础1
- 第二部分:线程同步基础2
- 第二部分:线程同步基础3
- Synchronization 同步
- Delphi Thread 线程同步
- Thread 线程同步
- iOS:多线程编程指南(三)--线程同步 Synchronization
- Java7并发编程指南——第二章:线程同步基础
- C#中的多线程 -第二部分:线程同步基础
- 第二篇:中小企业特点和信息化难点
- 惯性动作捕捉设备的发展和原理初步介绍
- python入门(十二):装饰器详解
- redis-4.0.0集群操作步骤及错误解决
- 智能专项练习--HTML+CSS+bootstrap(2)
- 第二章 Basic Thread Synchronization (基础线程同步) 【下】
- spring+springMVC中使用@Transcational方式管理事务的必须要配的东西。
- 使用Python Pandas处理亿级数据
- 集合框架(数据结构之数组和链表)
- Oracle查看锁表与解锁方法
- ERROR ITMS-90086: "Missing 64-bit support. iOS apps submitted to the App Store must include 64-bit s
- Android学习(七)Adapter
- selinux内核级加强型防火墙
- 2017 Multi-University Training Contest