如果一個B/S的應用,并發量在2000以上時,新建的對象累積會占用大量內存,當超過一定數量的時候,會報內存不夠,使用享元模式就可以解決這一問題,也就是建立對象池。現在的方案可以使用
Apache Commons Pool。
一、基本String對象測試
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.apache.commons.pool.BaseKeyedPoolableObjectFactory;


/** *//**
* Created by IntelliJ IDEA.
*
* @author leizhimin 2009-10-27 17:46:18
*/

public class Test
{

public static void main(String[] args) throws Exception
{
//創建一個對象池

GenericKeyedObjectPool pool = new GenericKeyedObjectPool(new BaseKeyedPoolableObjectFactory()
{
@Override

public Object makeObject(Object o) throws Exception
{
return o;
}
});

//添加對象到池,重復的不會重復入池
pool.addObject("a");
pool.addObject("a");
pool.addObject("b");
pool.addObject("x");

//清除最早的對象
pool.clearOldest();

//獲取并輸出對象
System.out.println(pool.borrowObject("a"));
System.out.println(pool.borrowObject("b"));
System.out.println(pool.borrowObject("c"));
System.out.println(pool.borrowObject("c"));
System.out.println(pool.borrowObject("a"));

//輸出池狀態
System.out.println(pool.getMaxIdle());
System.out.println(pool.getMaxActive());

}
}輸出結果:
a
b
c
c
a
8
8
Process finished with exit code 0
二、自定義復雜對象測試
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.apache.commons.pool.BaseKeyedPoolableObjectFactory;


/** *//**
* Created by IntelliJ IDEA.
*
* @author leizhimin 2009-10-27 17:46:18
*/

public class Test
{

public static void main(String[] args) throws Exception
{
//創建一個對象池

GenericKeyedObjectPool pool = new GenericKeyedObjectPool(new BaseKeyedPoolableObjectFactory()
{
@Override

public Object makeObject(Object o) throws Exception
{
if (o != null && o instanceof User)
return o;
else
return null;
}
});

//添加對象到池,重復的不會重復入池
pool.addObject("a");
pool.addObject("b");
pool.addObject("x");
pool.addObject(null);
pool.addObject(null);
pool.addObject(null);
pool.addObject(new User("zhangsan", "123"));
pool.addObject(new User("lisi", "112"));
pool.addObject(new User("lisi", "112", 32));
pool.addObject(new User("lisi", "112", 32, "一個爛人!"));


//清除最早的對象
pool.clearOldest();

//獲取并輸出對象
User u1 = new User("lisi", "112", 32, "一個爛人!");
System.out.println(pool.borrowObject(u1));
pool.returnObject(u1,u1);

//獲取并輸出對象
User u2 = new User("lisi", "112", 32, "一個爛人!");
System.out.println(pool.borrowObject(u2));
pool.returnObject(u2,u2);

//獲取并輸出對象
User u3 = new User("lisi", "112", 32);
System.out.println(pool.borrowObject(u3));
pool.returnObject(u3,u3);

//獲取并輸出對象
User u4 = new User("lisi", "112");
System.out.println(pool.borrowObject(u4));
pool.returnObject(u4,u4);

System.out.println(pool.borrowObject(u4));
pool.returnObject(u4,u4);
System.out.println(pool.borrowObject(u4));
pool.returnObject(u4,u4);
System.out.println(pool.borrowObject(u4));
pool.returnObject(u4,u4);
System.out.println(pool.borrowObject(u4));
pool.returnObject(u4,u4);
System.out.println(pool.borrowObject(u4));
pool.returnObject(u4,u4);
System.out.println(pool.borrowObject(u4));
pool.returnObject(u4,u4);
System.out.println(pool.borrowObject(u4));
pool.returnObject(u4,u4);





System.out.println(pool.borrowObject(new User("lisi", "112")));
// System.out.println(pool.borrowObject(new User("lisi", "112")));

//輸出池狀態
System.out.println(pool.getMaxIdle());
System.out.println(pool.getMaxActive());
pool.clearOldest();
pool.close();

}
}


class User
{
private String name;
private String pswd;
private int age;
private String reamark;


User()
{
}


User(String name, String pswd)
{
this.name = name;
this.pswd = pswd;
}


User(String name, String pswd, int age)
{
this.name = name;
this.pswd = pswd;
this.age = age;
}


User(String name, String pswd, int age, String reamark)
{
this.name = name;
this.pswd = pswd;
this.age = age;
this.reamark = reamark;
}


public String getName()
{
return name;
}


public void setName(String name)
{
this.name = name;
}


public String getPswd()
{
return pswd;
}


public void setPswd(String pswd)
{
this.pswd = pswd;
}


public int getAge()
{
return age;
}


public void setAge(int age)
{
this.age = age;
}


public String getReamark()
{
return reamark;
}


public void setReamark(String reamark)
{
this.reamark = reamark;
}

@Override

public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

User user = (User) o;

if (!name.equals(user.name)) return false;
if (!pswd.equals(user.pswd)) return false;

return true;
}

@Override

public int hashCode()
{
int result = name.hashCode();
result = 31 * result + pswd.hashCode();
return result;
}

@Override

public String toString()
{
return "User{" +
"name='" + name + '\'' +
", pswd='" + pswd + '\'' +
", age=" + age +
", reamark='" + reamark + '\'' +
'}';
}
}測試結果:
User{name='lisi', pswd='112', age=32, reamark='
null'}
User{name='lisi', pswd='112', age=32, reamark='一個爛人!'}
User{name='lisi', pswd='112', age=32, reamark='一個爛人!'}
User{name='lisi', pswd='112', age=32, reamark='
null'}
User{name='lisi', pswd='112', age=0, reamark='
null'}
User{name='lisi', pswd='112', age=0, reamark='
null'}
User{name='lisi', pswd='112', age=0, reamark='
null'}
User{name='lisi', pswd='112', age=0, reamark='
null'}
User{name='lisi', pswd='112', age=0, reamark='
null'}
User{name='lisi', pswd='112', age=0, reamark='
null'}
User{name='lisi', pswd='112', age=0, reamark='
null'}
User{name='lisi', pswd='112', age=0, reamark='
null'}
8
8
Process finished with exit code 0
這次測試得出一些有用的結論:
1、復雜對象應該實現equals() 、hashCode()方法,以便不重復入池。
2、對于非入池的目標對象,比如a、b、x字符串,目前沒有有效的辦法過濾掉,不讓其入池,雖然在工廠方法里做了努力。
3、試圖將null入池,不會成功的,但也不拋異常。
4、對于池對象,使用應該遵循“接而有還,再借不難”-----從池中獲取,不用時候歸池,否則當池中沒有空閑可用的對象時候,程序會處于等待狀態,如果沒有顯式的調用歸還方法,則造成程序死鎖。
池的大小是初始化配置的,在沒有顯式配置指定的情況下,池大小默認為8.可以通過
GenericKeyedObjectPool.Config來配置。