等待超时模式:
假设等待时间为 T ,在当前时间NOW + T 之后就会超时
等待超时模式伪代码:
/**
* 等待的时间
*/
long remain = T;
/**
* 超时时间
*/
long overtime = now + T;
while (result 不满足条件 && remain > 0){
// 进入等待
wait(remain);
// 时间重新赋值 计算剩余等待时间
remain = overtime - now;
}
result result;
使用等待超时模式实现一个简单的数据库连接池
package org.dance.day1.pool;
import org.dance.tools.SleepTools;
import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
/**
* 数据库连接
* @author ZYGisComputer
*/
public class SqlConnection implements Connection {
/**
* 获取数据库连接
* @return
*/
public static final Connection fetchConnection(){
return new SqlConnection();
}
@Override
public void commit() throws SQLException {
SleepTools.ms(70);
}
@Override
public Statement createStatement() throws SQLException {
SleepTools.ms(1);
return null;
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return null;
}
@Override
public String nativeSQL(String sql) throws SQLException {
return null;
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
}
@Override
public boolean getAutoCommit() throws SQLException {
return false;
}
@Override
public void rollback() throws SQLException {
}
@Override
public void close() throws SQLException {
}
@Override
public boolean isClosed() throws SQLException {
return false;
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return null;
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
}
@Override
public boolean isReadOnly() throws SQLException {
return false;
}
@Override
public void setCatalog(String catalog) throws SQLException {
}
@Override
public String getCatalog() throws SQLException {
return null;
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
}
@Override
public int getTransactionIsolation() throws SQLException {
return 0;
}
@Override
public SQLWarning getWarnings() throws SQLException {
return null;
}
@Override
public void clearWarnings() throws SQLException {
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return null;
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return null;
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
}
@Override
public void setHoldability(int holdability) throws SQLException {
}
@Override
public int getHoldability() throws SQLException {
return 0;
}
@Override
public Savepoint setSavepoint() throws SQLException {
return null;
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
return null;
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return null;
}
@Override
public Clob createClob() throws SQLException {
return null;
}
@Override
public Blob createBlob() throws SQLException {
return null;
}
@Override
public NClob createNClob() throws SQLException {
return null;
}
@Override
public SQLXML createSQLXML() throws SQLException {
return null;
}
@Override
public boolean isValid(int timeout) throws SQLException {
return false;
}
@Override
public void setClientInfo(String name, String value) throws SQLClientInfoException {
}
@Override
public void setClientInfo(Properties properties) throws SQLClientInfoException {
}
@Override
public String getClientInfo(String name) throws SQLException {
return null;
}
@Override
public Properties getClientInfo() throws SQLException {
return null;
}
@Override
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return null;
}
@Override
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return null;
}
@Override
public void setSchema(String schema) throws SQLException {
}
@Override
public String getSchema() throws SQLException {
return null;
}
@Override
public void abort(Executor executor) throws SQLException {
}
@Override
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
}
@Override
public int getNetworkTimeout() throws SQLException {
return 0;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}
package org.dance.day1.pool;
import java.sql.Connection;
import java.util.LinkedList;
/**
* 数据库连接池
*
* @author ZYGisComputer
*/
public class DBPool {
/**
* 连接池,采用LinkedList链表实现有序
*/
private static final LinkedList<Connection> pool = new LinkedList<Connection>();
/**
* 初始化池大小
* @param initialSize
*/
public DBPool(int initialSize) {
if (0 < initialSize) {
for (int i = 0; i < initialSize; i++) {
pool.addLast(SqlConnection.fetchConnection());
}
}
}
/**
* 获取数据库连接
* @param mills 超时时间
* @return connection 连接
* @throws InterruptedException 中断异常
*/
public Connection fetchConnection(long mills) throws InterruptedException {
// 需要锁住数据库池
synchronized (pool){
// 判断超时时间
if(0>mills){
// 如果小于0 那么永不超时
while(pool.isEmpty()){
pool.wait();
}
return pool.removeFirst();
}else{
// 获取过期时间
long overtime = System.currentTimeMillis() + mills;
// 获取等待时间
long remain = mills;
while (pool.isEmpty()&&remain>0){
pool.wait(remain);
remain = overtime - System.currentTimeMillis();
}
// 到这里的时候 要么是等待时间过期了 要么是连接池有连接了
Connection connection = null;
// 再次尝试去拿一下
if(!pool.isEmpty()){
connection = pool.removeFirst();
}
return connection;
}
}
}
/**
* 释放数据库连接
* @param connection
*/
public void releaseConnection(Connection connection){
if(null!=connection){
synchronized (pool){
pool.addLast(connection);
// 放回连接需要通知在线程池上等待的线程
pool.notifyAll();
}
}
}
}
package org.dance.day1.pool;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 测试数据库连接池
* @author ZYGisComputer
*/
public class DBPoolTest {
/**
* 初始化连接池
*/
static DBPool dbPool = new DBPool(10);
static CountDownLatch countDownLatch;
public static void main(String[] args) throws InterruptedException {
// 线程数量
int threadCount = 50;
countDownLatch = new CountDownLatch(threadCount);
// 每个线程操作的次数
int count = 20;
// 计数器:统计可以拿到链接的线程的数量
AtomicInteger get = new AtomicInteger();
// 计数器:统计没有拿到链接的线程的数量
AtomicInteger noGet = new AtomicInteger();
for (int i = 0; i < threadCount; i++) {
Thread thread = new Thread(new Worker(count,get,noGet),"worker_"+i);
thread.start();
}
countDownLatch.await();
System.out.println("总共尝试了:"+(threadCount * count));
System.out.println("拿到链接的次数:"+get.get());
System.out.println("没有拿到链接的次数:"+noGet.get());
}
static class Worker implements Runnable{
int count;
AtomicInteger get;
AtomicInteger noGet;
public Worker(int count, AtomicInteger get, AtomicInteger noGet) {
this.count = count;
this.get = get;
this.noGet = noGet;
}
@Override
public void run() {
while (count>0){
try {
// 从数据库连接池开始拿链接,如果1秒内没有拿到链接将会返回null
// 然后统计拿到和没拿到的数量
Connection connection = dbPool.fetchConnection(1000);
if(null!=connection){
try {
connection.createStatement();
connection.commit();
} finally {
dbPool.releaseConnection(connection);
get.incrementAndGet();
System.out.println(Thread.currentThread().getName()+":拿到了线程");
}
}else{
noGet.incrementAndGet();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
count--;
}
}
countDownLatch.countDown();
}
}
}
作者:彼岸舞
时间:2020\09\16
内容关于:并发编程
本文来源于网络,只做技术分享,一概不负任何责任