0

How can I ensure that every thread is working on the same object? We're executing regression on 8 threads parallel. I want to store thread-specific logs in a map, then, after run, do something with the data inside it.

public class Foo {
   // map with thread name as a key and queue to keep its logs
   public static final Map<String, LinkedList<String>> foofoo = new ConcurrentHashMap<>();
   
   
   public static void addToQueue(String threadName, String log) {
      //some logic here to add log to proper queue
   }
}

I want to make sure that whenever any of running threads invokes:

Foo.addToQueue("foo", "fooo");

it is accessing the same map. Thank you for your responses. I'm kind of confused with multi threading, sorry if the question is a bit dumb. Have a nice day! :)

Edit: in the sample up there I've used final keyword when initializing this object, because I know that it blocks objects reference. However does it solve my problem? Is there any better approach?

lacki
  • 1
  • 1

2 Answers2

0

You can use the synchronised keyword in your method signature. When a synchronised method is called from a thread, it (the thread) automatically acquires a lock on the shared object. So what you can do is make the addToQueue method synchronised. Read more.

Alternatively, Check this out. It is quite an informative thread on Collections.synchronisedList. Have a working example also.

dravit
  • 553
  • 6
  • 16
0

My understanding

  1. Aggregate information per thread
  2. Collect this aggregated data in the main thread

Sample Code

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class ThreadParallel {

    public static void main(String[] args) {
        List<Integer> input = IntStream.range(0, 100).boxed().collect(Collectors.toList());
        class ThreadSpecific {

            final String threadName;
            final String num;

            ThreadSpecific(int num) {
                threadName = Thread.currentThread().getName();
                this.num = Integer.toString(num);
            }

            public String getThreadName() {
                return threadName;
            }

            public String getNums() {
                return num;
            }
        }

        Map<String, List<String>> result = input.parallelStream()
            .map(i -> new ThreadSpecific(i))
            .collect(Collectors.groupingByConcurrent(ThreadSpecific::getThreadName,
                Collectors.mapping(ThreadSpecific::getNums, Collectors.toList())));
        System.out.println(result);
    }
}

Alternatively, if the inner aggregated object is list(or collection), then try something like:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class ThreadParallel {

    public static void main(String[] args) {
        List<Integer> input = IntStream.range(0, 100).boxed().collect(Collectors.toList());
        class ThreadSpecific {

            final String threadName;
            final List<String> nums;

            ThreadSpecific(int num) {
                threadName = Thread.currentThread().getName();
                this.nums = new ArrayList<>();
                nums.add(Integer.toString(num));
            }

            public String getThreadName() {
                return threadName;
            }

            public List<String> getNums() {
                return nums;
            }
        }

        Map<String, List<String>> result = input.parallelStream()
            .map(i -> new ThreadSpecific(i))
            .collect(Collectors.groupingByConcurrent(ThreadSpecific::getThreadName,
                Collectors.mapping(ThreadSpecific::getNums,
                    Collectors.collectingAndThen(Collectors.toList(), nums -> nums.stream()
                        .flatMap(List::stream).collect(Collectors.toList())
                ))));
        System.out.println(result);
    }
}

Notes

Edit: in the sample up there I've used final keyword when initializing this object, because I know that it blocks objects reference. However does it solve my problem? Is there any better approach?
The purpose of final in reference variables are 1. Catches any accidental/unexpected reassignment to the reference variable (only reference variable is immutable) 2. The immutable property of reference variable ensures the `L`[123] caches will maintain a consistent state of this reference variable in multithreaded execution.(possibly in single threaded execution with multiple cpus). 3. This feature avoids the need for `volatile`
Thiyanesh
  • 2,360
  • 1
  • 4
  • 11