2

与 Singleton 类类似,我想创建一个 Fiveton 类,它可以创建最多 5 个该类的实例。不同的线程正在尝试访问此类的实例(因此需要提供 getInstance 方法)。然而类很重,所以不能急切地创建实例,即按需创建。

另一个约定是线程以循环方式分配实例,即线程 1、6、11 获得 Fiveton 对象的实例 1。如果实例正在被线程使用,它们会等待锁(线程 6 和 11 可能会等待实例 1,而线程 11 可能会获得它,但在任何情况下线程 11 都不应该获得实例 2)。同样,线程号。2、7、12 应该得到实例 2。

4

3 回答 3

3

不要在你的类本身中编写代码*,而是使用对象池。

Apache Commons / Pool是一个很好的入门库

另一个我不知道但声称更快的是furious-objectpool

使用提供的实现之一或使用库作为构建您自己的自定义池的基础。

* 为什么不将其编码到类本身中?因为类做什么以及如何访问类的实例是不相关的问题。课程应该专注于它的核心目的,而不是管理自己。

于 2013-04-10T08:16:25.387 回答
1

如果您关心创建实例时的争用(即您不希望线程 6 阻塞,因为线程 2 仍在创建它的实例),您可以使用锁条带策略 - 在此实现中,假设线程 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;
        }
    }
}
于 2013-04-10T14:19:07.653 回答
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 )所指出的那样,您可以使用它来管理实例,并为您希望以这种方式更清洁和透明的逻辑使用不同的类(对象)。

更新

添加了延迟初始化

于 2013-04-10T08:28:56.407 回答