Semaphore學習

Semaphore是一種在多線程環境下使用的設施,該設施負責協調各個線程,以保證它們能夠正確、合理的使用公共資源的設施,
也是操作系統中用於控制進程同步互斥的量。Semaphore是一種計數信號量,用於管理一組資源,內部是基於AQS的共享模式。
它相當於給線程規定一個量從而控制允許活動的線程數。

利用Semaphore設計一個鏈接池。

package com.business.thread.Semaphore;

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
//數據庫連接的平庸實現
public class SqlConnectionImpl implements Connection{

    //重寫Connection的方法,此處省略    

	//拿一個數據庫連接
	public static final Connection fetchConnection() {
		// TODO Auto-generated method stub
		return new SqlConnectionImpl();
	}

}
package com.business.thread.Semaphore;
//一個使用Semaphore實現的數據庫連接池

import java.sql.Connection;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;
/*Semaphore是一種在多線程環境下使用的設施,該設施負責協調各個線程,以保證它們能夠正確、合理的使用公共資源的設施,
也是操作系統中用於控制進程同步互斥的量。Semaphore是一種計數信號量,用於管理一組資源,內部是基於AQS的共享模式。
它相當於給線程規定一個量從而控制允許活動的線程數。*/

public class DBPoolSemaphore {
	//連接池的大小爲10
	private final static int POOL_SIZE = 10;
	//存放連接的容器
	private static LinkedList<Connection> pool = new LinkedList<Connection>();
	//分別表示可用連接和已用連接
	private final Semaphore useFul,useLess;
	
	//初始化線程池
	static {
		for(int i=0;i<POOL_SIZE;i++) {
			pool.addLast(SqlConnectionImpl.fetchConnection());
		}
	}
	/*
	 * Semaphore主要構造方法 
	 * Semaphore(int permits):構造方法,創建具有給定許可數的計數信號量並設置爲非公平信號量。
	 * Semaphore(int permits,booleanfair):構造方法,當fair等於true時,創建具有給定許可數的計數信號量並設置爲公平信號量。 void
	 * acquire():從此信號量獲取一個許可前線程將一直阻塞。相當於一輛車佔了一個車位。 void acquire(int
	 * n):從此信號量獲取給定數目許可,在提供這些許可前一直將線程阻塞。比如n=2,就相當於一輛車佔了兩個車位。 void
	 * release():釋放一個許可,將其返回給信號量。就如同車開走返回一個車位。 void release(int n):釋放n個許可。
	 * int availablePermits():當前可用的許可數。
	 */

	public DBPoolSemaphore(){
		this.useFul = new Semaphore(POOL_SIZE);
		this.useLess = new Semaphore(0);
	}
	//歸還連接
	public void returnConnection(Connection connection) throws InterruptedException {
		if(connection!=null) {
			System.out.println("當前有"+useFul.getQueueLength()+"個線程等待數據庫連接!"+
		"可用連接數: "+useFul.availablePermits());
			useLess.acquire();
			//對這個池進行加鎖
			synchronized (pool) {
				pool.add(connection);
			}			
			useFul.release();
		}
	}
	//從池子拿連接
	public Connection takeConnection() throws InterruptedException {
		useFul.acquire();
		Connection connection;
		synchronized (pool) {
			connection = pool.removeFirst();
		}
		useLess.release();
		
		return connection;
		
	}
	
}

 

package com.business.thread.Semaphore;

import java.sql.Connection;
import java.util.Random;
//測試數據庫連接池
public class AppTest {
	private static DBPoolSemaphore dbPool = new DBPoolSemaphore();
	//拿數據庫連接的線程
	private static class busiThread extends Thread{
		public void run() {
			Random r = new Random();//讓每個線程有個鏈接時間不一樣
			long start = System.currentTimeMillis();
			Connection connection;
			try {
				connection = dbPool.takeConnection();
				System.out.println("Thread_"+Thread.currentThread().getId()+
						"_獲取數據庫連接共耗時【"+(System.currentTimeMillis()-start)+"】ms");
				Thread.sleep(100+r.nextInt(100));
				System.out.println("查詢數據完成,歸還連接");
				dbPool.returnConnection(connection);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
	}
	
	
	public static void main(String[] args) {
		for(int i = 0;i<50;i++) {
			Thread thread = new busiThread();
			thread.start();
		}
	}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章