与Singleton类似,我想创建一个Fiveton类,它可以创建最多5个类的实例。不同的线程正在尝试访问此类的实例(因此需要提供getInstance方法)。但是类很重,所以不能急切地创建实例,即按需创建。
同样合同是线程以循环方式分配实例,即线程号1,6,11获得Fiveton对象的实例1。如果线程正在使用该实例,则它们等待锁定(线程6和11可能等待实例1并且线程11可能得到它但在任何情况下线程11都不应该获得实例2)。同样,线程号。 2,7,12应该得到实例2.
答案 0 :(得分:3)
不要在类本身中编写代码*,而是使用对象池。
让您入门的好图书馆是Apache Commons / Pool
另一个我不知道但声称速度更快的是furious-objectpool
使用其中一个提供的实现或使用库作为构建您自己的自定义池的基础。
*为什么不在课堂上编码呢?因为类的作用以及如何访问类的实例是无关紧要的问题。课程应该专注于它的核心目的而不是管理自己。
答案 1 :(得分:1)
如果您在创建实例时关心争用(即您不希望线程6因为线程2仍在创建其实例而阻塞),您可以使用锁定条带化策略 - 在此实现中,假设为Thread 1,2,......一个接一个地呼叫getInstance
:
class CyclicFiveton {
private static final CyclicFiveton[] fivetons = new CyclicFiveton[5];
private static final Object[] locks = new Object[5];
private static final AtomicInteger counter = new AtomicInteger();
static {
for (int i = 0; i < 5; i++) {
locks[i] = new Object();
}
}
private CyclicFiveton() {
}
public static CyclicFiveton getInstance() {
int index = counter.getAndIncrement() % 5;
synchronized (locks[index]) {
CyclicFiveton fiveton = fivetons[index];
if (fiveton == null) {
fiveton = new CyclicFiveton();
fivetons[index] = fiveton;
}
return fiveton;
}
}
}
答案 2 :(得分:0)
如果我理解你的要求你可以尝试这样的事情:
public class Fiveton {
private Fiveton(){
//create private constructor to prevent new instances from outside of the class
}
private static final int MAX_NB_INSTANCES = 5;
private static List<Fiveton> instances;
/**
* Should be called once at the beginning
*/
public static void init(){
instances = new ArrayList<Fiveton>(MAX_NB_INSTANCES);
for(int i=0;i<MAX_NB_INSTANCES;i++){
instances.add(new Fiveton());
}
}
/**
* threadNb can be the name of the Thread::getName()
*
* @param threadNb
* @return Fiveton
*/
public static Fiveton getInstance(int threadNb){
synchronized(instances.get(threadNb%MAX_NB_INSTANCES)){
return instances.get(threadNb%MAX_NB_INSTANCES);
}
}
/**
* other logic
*
*/
}
您只需要添加Fiveton对象背后的逻辑。
<强>更新强>
或者 Sean Patrick Floyd 指出你可以使用它来管理实例,并为你想要的逻辑提供不同的类(对象)这种方式更清洁透明。
<强>更新强>
添加了延迟初始化