设计单件管理器线程安全

时间:2018-03-29 10:17:18

标签: java multithreading list thread-safety singleton

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

  • A :在列表中添加/删除主题wchill。
  • 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 正在检查列表中是否包含元素。 (因为经理的单身设计)

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

您可以向我推荐哪种解决方案?

我还想到了一种解决方案,可以通过每种类型的线程来生成管理器的两个实例。你觉得怎么样?

非常感谢:)

1 个答案:

答案 0 :(得分:0)

我制作了一个新设计: 它是一个SingletonManager,修复了两个实例。 线程类型A将仅使用第一个实例在地图中添加元素。 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"));

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