看到一个重入锁的介绍很有意思:
一个有娃的父亲正在打水,他的娃也到井边了,所以女凭父贵直接排到最前面打水,羡煞旁人了。
以上这个故事模型就是所谓的公平锁模型,当一个人想到井边打水,而现在打水的人又不是自家人,这时候就得乖乖在队列后面排队。
事情总不是那么一帆风顺的,总会有些人想走捷径,话说看井人年纪大了,有时候,眼力不是很好,这时候,人们开始打起了新主意。新来打水的人,他们看到有人排队打水的时候,他们不会那么乖巧的就排到最后面去排队,反之,他们会看看现在有没有人正在打水,如果有人在打水,没辄了,只好排到队列最后面,但如果这时候前面打水的人刚刚打完水,正在交接中,排在队头的人还没有完成交接工作,这时候,新来的人可以尝试抢打水权,如果抢到了,呵呵,其他人也只能睁一只眼闭一只眼,因为大家都默认这个规则了。这就是所谓的非公平锁模型。新来的人不一定总得乖乖排队,这也就造成了原来队列中排队的人可能要等很久很久
两种重入锁:都可实现阻塞
Synchronized
ReentrantLock
利用重入锁的阻塞机制实现数据库连接池:其实就是使用这两种锁实现生产者消费者机制
Synchronized的实现方式,实现一个简单的数据库连接池
public class SyJDBC {
public static void main(String[] args) throws InterruptedException {
Pool p=new Pool(2,4);
for(int i=0;i<10;i++) {
new Thread(new Runnable() {
@Override
public void run() {
p.getjdbc();
}
}).start();
}
for(int i=0;i<10;i++) {
int data=i;
new Thread(new Runnable() {
@Override
public void run() {
String name="zhangsan"+(data);
p.removejdbc(name);
}
}).start();
}
}
static class Pool {
int size=3;//连接数
int maxsize=10;//允许的最大连接数
int pool_size=0;//空闲连接数
int testname=0;
Map<String,Boolean> poolmap=new HashMap<>();
public Pool(int size, int maxsize) {
this.size = size;
this.maxsize = maxsize;
}
public synchronized String getjdbc(){
for(String key:poolmap.keySet()){
if(poolmap.get(key).equals(false)){
poolmap.put(key,true);
System.out.println("调用连接"+key);
if(pool_size>0){
pool_size--;
}
notify();
return key;
}
}
if(poolmap.size()<maxsize){
String name="zhangsan"+(testname++);
poolmap.put(name,true);
System.out.println("调用连接"+name);
notify();
return name;
}else{
try {
System.out.println("等待");
for(int i=0;i<5;i++){
wait(5000);
getjdbc();
}
}catch (InterruptedException e){
e.printStackTrace();
}
return null;
}
}
public synchronized void removejdbc(String name){
System.out.println("准备断开连接:>>>>>>>>>>>>>"+name);
if(poolmap.containsKey(name)){
if(poolmap.size()>size){
if(pool_size>=(size/2)){
poolmap.remove(name);
System.out.println("断开连接:"+name);
notify();
return ;
}
}
poolmap.put(name,false);
System.out.println("断开连接:"+name+"--"+false);
pool_size++;
notify();
}
}
}
}
打印:由于连接的名字是“zhangshan”+变量的形式,采用多线程调用的时候可能会导致找不到建立的连接
采用ReentrantLock的方式实现简单的数据库连接池
package com.smile.test.zxyte.java;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author zhangxiaoyan
* @date 2019/8/27 15:17
* 描述:
*/
public class LockJDBC {
public static void main(String[] args) {
Pool p=new Pool(2,4);
for(int i=0;i<10;i++) {
new Thread(new Runnable() {
@Override
public void run() {
p.getjdbc();
}
}).start();
}
for(int i=0;i<10;i++) {
int data=i;
new Thread(new Runnable() {
@Override
public void run() {
String name="zhangsan"+(data);
p.removejdbc(name);
}
}).start();
}
}
static class Pool{
int size=3; //连接数
int maxsize=10;//最大连接数
int pool_size=0;//空闲数量
int testname=0;
Lock lock =new ReentrantLock(true);
Condition lockcondition=lock.newCondition();
Map<String,Boolean> poolmap=new HashMap<>();
public Pool(int size, int maxsize) {
this.size = size;
this.maxsize = maxsize;
}
public String getjdbc(){
lock.lock();
try {
for (String key : poolmap.keySet()) {
if (poolmap.get(key).equals(false)) {
poolmap.put(key, true);
System.out.println("调用连接" + key);
if (pool_size > 0) {
pool_size--;
}
return key;
}
}
if (poolmap.size() < maxsize) {
String name = "zhangsan" + (testname++);
poolmap.put(name, true);
System.out.println("调用连接" + name);
return name;
} else {
System.out.println("等待");
lockcondition.await(60*1000, TimeUnit.MILLISECONDS);
getjdbc();
return null;
}
}catch (Exception ex){
ex.printStackTrace();
return null;
}finally {
lock.unlock();
}
}
public void removejdbc(String name){
lock.lock();
try {
System.out.println("准备断开连接:>>>>>>>>>>>>>" + name);
if (poolmap.containsKey(name)) {
if (poolmap.size() > size) {
if (pool_size >= (size / 2)) {
poolmap.remove(name);
System.out.println("断开连接:" + name);
lockcondition.signal();
return;
}
}
poolmap.put(name, false);
System.out.println("断开连接:" + name + "--" + false);
pool_size++;
lockcondition.signal();
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
结果:
ReentrantLock和Condition结合通过阻塞实现生产者消费者模式其实还蛮有意思的。