2

I'm thinking of a solution for a problem, I want to synchronized a List, which will be accessed by two Type of Thread:

  • A: Thread wchill add/remove on the list.
  • B: Thread will check if the list contains a specific object.

The solution that i thinked about is :

SingletonManager will be synchronized:

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);
    }
}

The problem, is that the Thread A cannot try to add/remove on the list while Thread B is checking if an element is contained on the List. (because of singleton design of the Manager)

And my need is that both thread B and A access simultaneously to the list for differents task. And synchronization should stay only on method delegate for each Thread.

Which solution can you advice me?

I also thinked of a solution to make two instances of the Manager by each type of thread. What do you think about it ?

Many thanks :)

  • 2
    You mention list but use map - which one you want? And if you already use `ConcurrentHashMap` then you don't need additional synchronization... – Maciej Mar 29 '18 at 10:23
  • 1
    As a sidenote: If you are using Singletons, use the `enum` implementation for them. Compare [this](https://stackoverflow.com/questions/26285520/implementing-singleton-with-an-enum-in-java) – Ben Mar 29 '18 at 10:23
  • [Lock](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html) may help – Thum Choon Tat Mar 29 '18 at 10:26
  • I will use Map, But the instance of the singleton will be shared by both type of Threads. So a type of thread will wait that the instance is available. and this is what i don't want. i want that each thread have instance of class available and make synchronization only on method. I know that it's principe of Singleton, but is there any solution to have exacty only two instance (one will be used by Threads of type A and the second by the Threads of type B) ? – Abdelhakim Ait Errami Mar 29 '18 at 10:29

1 Answers1

0

I make a new design : it's a SingletonManager with two instances fixed. The type A of Thread will only use the first Instances to add elements in the map. The type B thread will use second instance to read element in the 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;
    }
}

Exemple Test:

   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"));

Maybe there is an easy solution to handle this case, what do you think about?