Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to use ConcurrentHashMap in a MultiThread application with Callable

I want to have a threading application and I use Callable interface, but I want all the threads to add simultaneously in a ConcurrentHashmap some values, and at the end of the program to print the hashmap with the results.
More specifically, I have a list with some names. I iterate through the list and combine threading and in each thread if the name’s length is shorter than 5 , then I want it added to the concurrent hashmap.
At the end of the program I want to print the concurrent hashmap with all the names that are shorter than 5.

So my main class is the following:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class AddElementsToMap {

    public static void main(String[] args) {
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();

        List<String> list = new ArrayList<String>();

        list.add("Dimitrios");
        list.add("Maria");
        list.add("Jason");
        list.add("Io");
        list.add("Jessica");

        ExecutorService executor = Executors.newFixedThreadPool(3);
        ArrayList<Future<Object>> futureList = new ArrayList<Future<Object>>();

        for (String name : list) {

            Future future = executor.submit(new AddElementsToMapCallable(name, map));
            futureList.add(future);

        }

        executor.shutdown();

        System.out.println("MAP " + map);

    }

}

and My Callable is the following

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

public class AddElementsToMapCallable implements Callable {

    private String name;
    private String className;
    ConcurrentHashMap<String, String> map;

    public AddElementsToMapCallable(String name, ConcurrentHashMap<String, String> map) {

        this.className = this.getClass().getSimpleName();
        this.name = name;
        this.map = map;
    }

    @Override
    public Object call() throws Exception {
        HashMap<String, String> map = new HashMap<String, String>();
        System.out.println(
                className + "call" + " ThreadID = " + Thread.currentThread().getId() + " Processing User = " + name);
        if (name.length() <= 5) {
            System.out.println(className + "call" + " ThreadID = " + Thread.currentThread().getId()
                    + " Processing User = " + name + "length is smaller than 5. Adding!");

            map.put(name, String.valueOf(name.length()));
        } else {
            System.out.println(className + "call" + " ThreadID = " + Thread.currentThread().getId()
                    + " Processing User = " + name + "length is BIGGER than 5");

        }

        return map;
    }

    public long getThreadId() {
        return Thread.currentThread().getId();
    }

    public Thread getThread() {
        return Thread.currentThread();
    }
}

but what I get as a result is as you can see not what I wanted…

 MAP {}
    AddElementsToMapCallablecall ThreadID = 14 Processing User = Maria
    AddElementsToMapCallablecall ThreadID = 13 Processing User = Dimitrios
    AddElementsToMapCallablecall ThreadID = 15 Processing User = Jason
    AddElementsToMapCallablecall ThreadID = 14 Processing User = Marialength is smaller than 5. Adding!
    AddElementsToMapCallablecall ThreadID = 13 Processing User = Dimitrioslength is BIGGER than 5
    AddElementsToMapCallablecall ThreadID = 15 Processing User = Jasonlength is smaller than 5. Adding!
    AddElementsToMapCallablecall ThreadID = 15 Processing User = Io
    AddElementsToMapCallablecall ThreadID = 15 Processing User = Iolength is smaller than 5. Adding!
    AddElementsToMapCallablecall ThreadID = 15 Processing User = Jessica

AddElementsToMapCallablecall ThreadID = 15 Processing User = Jessicalength is BIGGER than 5

Could someone help me? What am I doing wrong??
Thanks !

>Solution :

Scope issue of map variable passed in the constructor and the first line of method call. If you want to add the entries into the Map passed in the constructor you can try something like this:

public class AddElementsToMap {

    public static void main(String[] args) {
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();

        List<String> list = new ArrayList<String>();

        list.add("Dimitrios");
        list.add("Maria");
        list.add("Jason");
        list.add("Io");
        list.add("Jessica");

        ExecutorService executor = Executors.newFixedThreadPool(3);
        ArrayList<Future<Object>> futureList = new ArrayList<Future<Object>>();

        for (String name : list) {

            Future future = executor.submit(new AddElementsToMapCallable(name, map));
            futureList.add(future);

        }

        // Wait until all threads are finished (Hopefully this is jsut for a learning experience)
        try {
            for (Future f : futureList) {
                f.get();
            }
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace(System.err);
        }

        executor.shutdown();

        System.out.println("MAP " + map);

    }


    static class AddElementsToMapCallable implements Callable {

        private String name;
        private String className;
        ConcurrentHashMap<String, String> map;

        public AddElementsToMapCallable(String name, ConcurrentHashMap<String, String> map) {

            this.className = this.getClass().getSimpleName();
            this.name = name;
            this.map = map;
        }

        @Override
        public Object call() throws Exception {
            HashMap<String, String> map = new HashMap<String, String>(); // REMOVE this line. This map will shadow the map passed in the constructor
            
            System.out.println(
                  className + "call" + " ThreadID = " + Thread.currentThread().getId()
                        + " Processing User = " + name);
            if (name.length() <= 5) {
                System.out.println(
                      className + "call" + " ThreadID = " + Thread.currentThread().getId()
                            + " Processing User = " + name + "length is smaller than 5. Adding!");

                map.put(name, String.valueOf(name.length()));
            } else {
                System.out.println(
                      className + "call" + " ThreadID = " + Thread.currentThread().getId()
                            + " Processing User = " + name + "length is BIGGER than 5");

            }

            return map;
        }

        public long getThreadId() {
            return Thread.currentThread().getId();
        }

        public Thread getThread() {
            return Thread.currentThread();
        }
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading