多线程系列三:Lock和Condition
有了synchronized为什么还要Lock?
因为Lock和synchronized比较有如下优点
1、 尝试非阻塞地获取锁
2、 获取锁的过程可以被中断
3、 超时获取锁
Lock的标准用法
package com.lgs; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* lgs
* 显示锁lock的标准写法
*/
public class LockTemplete { public static void main(String[] args) {
Lock lock = new ReentrantLock();
//获取锁
lock.lock();
try{
// do my work.....
}finally{
//释放锁
lock.unlock();
}
} }
Lock的常用方法
Lock() 获取锁
tryLock尝试非阻塞地获取锁
lockInterruptibly:获取锁的过程可以被中断
tryLock(long time, TimeUnit unit) 超时获取锁
unlock()释放锁
锁的可重入
一个线程获得了锁进入了同步代码块遇到了锁仍然可以进入同步代码块
递归的时候发生锁的重入,没有锁的可重入,就会死锁
公平和非公平锁
公平锁,先对锁发出获取请求的一定先被满足。公平锁的效率比非公平锁效率要低。
为什么非公平锁的性能要高:因为非公平锁是可以插队的,如线程C被唤醒变为可执行去获取锁的过程中,线程A插队进来直接获取锁执行自己的业务,线程A执行完以后,线程C刚好唤醒完直接就获取锁运行了,这样在线程C唤醒的过程中线程A就执行完了效率更高
读写锁ReentrantReadWriteLock
允许多个读线程同时进行,但是只允许一个写线程(不允许其他读线程防止脏读和写线程),支持读多写少场景,性能会有提升。
package com.lgs; import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; /**
* lgs
* 读写锁的使用
*/
public class RwLockTemplete { static final Map<String,String> map = new HashMap<>();
static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
static Lock r = reentrantReadWriteLock.readLock();
static Lock w = reentrantReadWriteLock.writeLock(); public void put(){
w.lock();
try{
// do my work.....
}finally{
w.unlock();
}
} public void get(){
r.lock();
try{
// do my work.....
}finally{
r.unlock();
}
} }
Condition接口有何用处?
Object的 wait,notify/notifyAll 实现等待通知机制
Condition接口和Lock配合来实现等待通知机制
Condition常用方法和使用范式
package com.lgs; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* lgs
* Condition的使用方式
*/
public class ConditionTemplete { Lock lock = new ReentrantLock();
Condition condition = lock.newCondition(); public void waitc() throws InterruptedException {
lock.lock();
try{
condition.await();
}finally{
lock.unlock();
}
} public void waitnotify() throws InterruptedException {
lock.lock();
try{
condition.signal();
//condition.signalAll();尽量少使用
}finally{
lock.unlock();
}
} }
结合ReentrantLock和Condition实现线程安全的有界队列
package com.lgs.bq; import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* lgs
* 结合ReentrantLock和Condition实现线程安全的有界队列
*/
public class BlockingQueueLC<T> {
private List queue = new LinkedList<>();
private final int limit;
Lock lock = new ReentrantLock();
private Condition needNotEmpty = lock.newCondition();
private Condition needNotFull = lock.newCondition(); public BlockingQueueLC(int limit) {
this.limit = limit;
} public void enqueue(T item) throws InterruptedException {
lock.lock();
try{
while(this.queue.size()==this.limit){
needNotFull.await();
}
this.queue.add(item);
//通知出队线程有数据可以取了
needNotEmpty.signal();
}finally{
lock.unlock();
}
} public T dequeue() throws InterruptedException {
lock.lock();
try{
while(this.queue.size()==0){
needNotEmpty.await();
}
//通知入队线程有位置可以入队了
needNotFull.signal();
return (T) this.queue.remove(0);
}finally{
lock.unlock();
}
}
}
package com.lgs.bq; /**
*
*/
public class BqTest {
public static void main(String[] args) {
BlockingQueueLC<Integer> bq = new BlockingQueueLC(10);
Thread threadA = new ThreadPush(bq);
threadA.setName("Push");
Thread threadB = new ThreadPop(bq);
threadB.setName("Pop");
threadB.start();
threadA.start();
} private static class ThreadPush extends Thread{
BlockingQueueLC<Integer> bq; public ThreadPush(BlockingQueueLC<Integer> bq) {
this.bq = bq;
} @Override
public void run() {
String threadName = Thread.currentThread().getName();
int i = 5;
while(i>0){
try {
Thread.sleep(500);
System.out.println(" i="+i+" will push");
bq.enqueue(i--);
} catch (InterruptedException e) {
//e.printStackTrace();
} }
}
} private static class ThreadPop extends Thread{
BlockingQueueLC<Integer> bq; public ThreadPop(BlockingQueueLC<Integer> bq) {
this.bq = bq;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+" will pop.....");
Integer i = bq.dequeue();
System.out.println(" i="+i.intValue()+" alread pop");
} catch (InterruptedException e) {
//e.printStackTrace();
}
} }
}
}
多线程系列三:Lock和Condition的更多相关文章
- java多线程系列(四)---Lock的使用
Lock的使用 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理 ...
- java多线程系列(三)---等待通知机制
等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...
- (Java多线程系列三)线程间通讯
Java多线程间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 1.使用wait()和notify()方法在线程中通讯 需求:第一个线程写入(input)用户,另一个线程 ...
- Java多线程系列三——实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式地加解锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- 【Java多线程系列三】实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式的加锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- Java多线程系列 JUC锁06 Condition条件
Condition介绍 Condition中提供了一组类似于Object中的监视器方法.与Lock配合可以完成等待通知模式. Lock lock = new ReentrantLock(); Cond ...
- Java多线程系列十——BlockingQueue
参考资料:http://ifeve.com/java-synchronousqueue/http://www.cnblogs.com/jackyuj/archive/2010/11/24/188655 ...
- java并发编程系列三、Lock和Condition
有了synchronized为什么还要Lock? 因为Lock和synchronized比较有如下优点 1. 尝试非阻塞地获取锁 2. 获取锁的过程可以被中断 3. 超时获取锁 Lock的标准用法 p ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
随机推荐
- lua 工具类(二)
local tonumber_ = tonumber function tonumber(v, base) end function toint(v) return math.round(tonumb ...
- C++文件读写 打开方式等比较全
要求:掌握文本文件读写的方法了解二进制文件的读写方法 C++文件流:fstream // 文件流ifstream // 输入文件流ofstream // 输出文件流 //创建一个文本文件并写入信息// ...
- linux Ctrl+z和Ctrl+c的区别
1.Ctrl+z 挂起进程,并不会结束,执行fg命令可以重新启动这个被挂起的命令. 2.Ctrl+c 终止进程
- hive sequencefile导入文件遇到FAILED: SemanticException Unable to load data to destination table. Error: The file that you are trying to load does not match the file format of the destination table.错误
hive sequencefile导入文件遇到FAILED: SemanticException Unable to load data to destination table. Error: Th ...
- Java使用HttpClient实现Post请求
http://www.cnblogs.com/mengrennwpu/p/6418114.html ******************************************* 基于项目需求 ...
- 【转】31个实用的find命令
find . -name "*.sql" -exec md5sum {} \; 一.主要内容 ====================================== . 用文 ...
- 【Professional English】Words Summary
01.数据库管理系统(Database Management Systems,DBMS) A database management system (DBMS) is a computer softw ...
- spring中xml配置方式和注解annoation方式(包括@autowired和@resource)的区别
xml文件中配置itemSqlParameterSourceProvider是可以的: <bean id="billDbWriter" class="com.aa. ...
- C++中的new、operator new与placement new
转:http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html new/delete与operator new/operator ...
- C# 裁剪图片
/// <summary> /// 生成缩略图 /// </summary> /// <param name="originalImagePath"& ...