0

我有一个类,我只想有一个实例。但是,我不希望多个线程调用getInstance(). 所以我用以下方式编码

public class SomeService implements Provider<String, Claims>{

    private SomeService(String a, String b, String c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }



    // single instance
    private static SomeService instance = null;

    private String a;
    private static AtomicInteger initialized = new AtomicInteger();
    private static CountDownLatch latch = new CountDownLatch(1);
    private String b;
    private String c;


    public static SomeService getInstance(String a, String b, String c) {
       if ( initialized.incrementAndGet() == 1) {
           instance = new SomeService(a, b, c);
           latch.countDown();
       } else {
           try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } 
       }
       return instance;

    }

    // Other implementation code

    }

我的意图(以及对此的理解)是:

  1. 当一个线程调用getInstance时,它会自动递增并检查它是否是所需的值。

  2. 如果没有,它将等待其他线程打开闩锁,这意味着初始化正在进行中。

如果有人帮助我纠正我的错误,那将会很有帮助。在我看来,我可能只是synchronized(someLockObject) {}阻止,但我想知道这是否有意义。

4

2 回答 2

1

我的意图(以及对此的理解)是:

1) 当一个线程调用 getInstance 时,它​​会自动递增并检查它是否是所需的值。

是的。

2)如果没有,它将等待其他线程打开闩锁,这意味着初始化正在进行中。

是的。

在我看来,我可能只能做synchronized(someLockObject) {}

是的,那会更典型。

我想知道这是否有意义。

该代码将按照您的意图工作,除非getInstance()被调用足够多次initialized以返回到 0。但是,我倾向于使用 anAtomicBoolean及其compareAndSet()方法,因为这似乎可以更好地模拟情况(并且它构成没有任何环绕的风险)。

然而,我更倾向于使用同步,除非这被证明是一个无法解决的性能问题。它更清晰,更易于访问。

但该方法总体上似乎构思不佳,因为getInstance()使用一组参数调用的线程可能会收到一个使用不同参数集初始化的实例。这可能表明您最好使用“仅使用一个”模式,而不是单例模式的这种变化。请特别注意,有些人认为 Singleton 是一种模式

于 2019-05-31T17:34:18.397 回答
0

我想这里的设计根本上是错误的。我认为我应该做的是

1)放置更多抽象层并确保使用构建器模式。

2)当我的服务需要服务时,它可以使用初始化属性来确定要使用的构建器,然后执行该工作。

3)如果可能的话,我也可以将它与工厂结合起来。

不知道以上是否有意义,但这消除了对反模式或“单例”的需要。

于 2019-06-01T17:15:54.330 回答