【问题标题】:Design for singleton Manager thread safe单例管理器线程安全的设计
【发布时间】:2018-09-08 06:15:50
【问题描述】:

我正在考虑一个问题的解决方案,我想同步一个List,它将被两种类型的线程访问:

  • A:添加/删除列表的线程。
  • B:线程将检查列表是否包含特定对象。

我想到的解决方案是:

SingletonManager 将被同步:

public class SingletonManager {

    // Instance of singleton Synchronized

    private static Map<String, String> myList = new ConcurrentHashMap<>();

    private static synchronized void addElement(String key, String value) {
        myList.put(key,value);
    }

    private static synchronized String getElement(String key) {
        return myList.get(key);
    }
}

问题在于,线程 A 无法尝试在列表中添加/删除,而线程 B 正在检查列表中是否包含元素。 (因为Manager的单例设计)

我的需要是线程 BA 同时访问不同任务的列表。并且同步应该只保留在每个线程的方法委托上。

您可以建议我哪种解决方案?

我还想到了一种解决方案,可以通过每种类型的线程创建 两个 Manager 实例。你怎么看?

非常感谢:)

【问题讨论】:

  • 您提到列表但使用地图-您想要哪一个?如果您已经使用ConcurrentHashMap,那么您不需要额外的同步...
  • 附带说明:如果您使用的是单例,请为它们使用 enum 实现。比较this
  • Lock 可能会有所帮助
  • 我将使用 Map,但是单例的实例将由两种类型的线程共享。因此,一种类型的线程将等待实例可用。这就是我不想要的。我希望每个线程都有可用的类实例,并且只在方法上进行同步。我知道这是单例的原理,但是有没有什么解决方案可以只拥有两个实例(一个由 A 类型的线程使用,第二个由 B 类型的线程使用)?

标签: java multithreading list thread-safety singleton


【解决方案1】:

我做了一个新设计: 这是一个固定了两个实例的 SingletonManager。 Thread 的类型 A 只会使用第一个 Instances 在地图中添加元素。 B 类线程将使用第二个实例来读取 Map 中的元素。

public class SingletonManager {

    private static Map<String, String> myList = new ConcurrentHashMap();

    private static SingletonManager INSTANCE_1 = null;
    private static SingletonManager INSTANCE_2 = null;
    public static int i = 0;

    private SingletonManager() {
    }

    public static SingletonManager getFirstInstance() {

        if (INSTANCE_1 == null) {
            INSTANCE_1 = new SingletonManager();
        }
        return INSTANCE_1;
    }

    public synchronized static SingletonManager getSecInstance() {
        if (INSTANCE_2 == null) {
            INSTANCE_2 = new SingletonManager();
        }
        return INSTANCE_2;
    }

    public synchronized void addElement(String key, String value) {
        myList.put(key,value);
    }

    public String getElement(String key) {
        return myList.get(key);
    }

    public Map<String, String> getList() {
        return myList;
    }
}

示例测试:

   public static void main(String[] args) throws InterruptedException {

        /* --- Thread for adding elements -- */
        Thread first = new Thread(new Runnable() {

            @Override
            public void run() {
                SingletonManager.getFirstInstance().addElement("1", "toto");
            }
        });
        Thread second = new Thread(new Runnable() {

            @Override
            public void run() {
                SingletonManager.getFirstInstance().addElement("2", "test");
            }
        });
        Thread troie = new Thread(new Runnable() {

            @Override
            public void run() {
                SingletonManager.getFirstInstance().addElement("3", "titi");
            }
        });

        Thread quatre = new Thread(new Runnable() {

            @Override
            public void run() {
                SingletonManager.getFirstInstance().addElement("4", "tata");
            }
    });

/* --- Thread for adding elements -- */
first.start();

second.start();

troie.start();

    quatre.start();

System.out.println(SingletonManager.getSecInstance().getElement("4"));

也许有一个简单的解决方案来处理这种情况,你怎么看?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-13
    • 2020-02-22
    • 2012-05-13
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多