多線程溢出寫法:
public class thisescape {
public thisescape(eventsource source) {
source.registerlistener(new eventlistener() {
public void onevent(event e) {
dosomething(e);
}
});
}
}
點評:加粗的這一段隐式this事件線程已經暴露給thisescape構造函數,而構造函數在該類中首先被其他類調用,是以整個this都暴露了。隻要其他線程在thisescape未構造之前(構造傳回狀态)調用這個類,那麼this就會被建立線程共享并識别它(線程溢出)。
是以正确的寫法:
public class thisescape{
private final eventlistener listener;
private thisescape() {
listener = new eventlistener() {
};
public static thisescape newinstance(eventsource source) {
thisescape safe = new thisescape();
source.registerlistener(safe.listener);
return safe;
點評:利用工廠模式來規避eventlistener線程溢出,建立的線程無法在構造函數之前共享和識别safe,進而保證線程安全。
我們在做jdbc連接配接一般也是采用工廠模式,但很少考慮是否存線上程溢出的現象,應盡量避免使用靜态塊,是以需要引起足夠的重視。
案例分析:
public class connectionpool {
private vector<connection> pool;
private string url="jdbc:mysql://localhost:3306/xxx";
private string username="root";
private string password="root";
private string driverclassname="com.mysql.jdbc.driver";
/**
* 連接配接池的大小,連接配接數
*/
private int poolsize=10;
private static connectionpool instance =null;
* 私有的構造方法,禁止外部建立本類的對象,要想獲得本類的對,通過getistance方法
* 使用了設計模式中的單子模式
private connectionpool(){
init();
}
private void init(){
pool =new vector<connection>(poolsize);
//readconfig();
addconnection();
public synchronized void release(connection conn){
pool.add(conn);
* 關閉連接配接池中所有資料庫的連接配接
public synchronized void closepool(){
for(int i=0;i<pool.size();i++){
try{
((connection)pool.get(i)).close();
}catch(sqlexception e){
e.printstacktrace();
}
pool.remove(i);
}
* 傳回目前連接配接池中的一個對象
public static connectionpool getinstance(){
if(instance==null){
instance=new connectionpool();
return instance;
* 傳回連接配接池中的一個資料庫連接配接
public synchronized connection getconnection(){
if(pool.size()>0){
connection conn=pool.get(0);
pool.remove(conn);
return conn;
}else{
return null;
private void addconnection(){
connection conn=null;
for(int i=0;i<poolsize;i++){
class.forname(driverclassname);
conn=drivermanager.getconnection(url,username,password);
pool.add(conn);
}catch(classnotfoundexception e){
}catch(sqlexception r){
r.printstacktrace();
private void readconfig(){
try{
string path=system.getproperty("use.dir")+"\\dbpool.properties";
fileinputstream is=new fileinputstream(path);
properties props=new properties();
props.load(is);
this.driverclassname=props.getproperty("driverclassname");
this.username=props.getproperty("username");
this.password=props.getproperty("password");
this.url=props.getproperty("url");
this.poolsize=integer.parseint(props.getproperty("poolsize"));
}catch(exception e){
e.printstacktrace();
system.out.println("讀取屬性檔案錯誤");
點評:這個連接配接池算是比較健全了,但還是有不足的地方,看下标記的綠色的部分應加上final,橙色加粗部分應加上volatile