How to start a Listener thread only once in a multithreaded program

45 views Asked by At

There is a Data class which holds a concurrent HashMap and add() method that adds elements to the map. Another class named User class which holds updateinfo() and when this method is triggered it calls the add() method of the Data class passing the necessary param.

in java

Now , I need a Listener Thread which simply does 2 thing in a loop . sleep for 1 second and then print all the elements of the map and make it empty ...

But the thing is that around 10000 threads will be concurrently calling the User.updateinfo() method and there is no main method where the program gets started so that how to efficiently place the listener thread so that it calls only once and it starts running in a place and the remaining tasks are being done without any complications.

==> Listener thread has to be started only once in this multithreaded program. Since it is a backend code no main method whenever user does a task updateinfo() is called.

since 10k threads trigger it can i place a thread pool executor so that it can be efficient in putting data in hashmap. guide me if im wrong

If there is a mistake in the architecture any constructive ideas are welcomed.

Thanks in advance.

1

There are 1 answers

0
Basil Bourque On

Rather than empty a ConcurrentMap concurrently, just replace it. Keep an AtomicReference instance that points to the latest map object.

final AtomicReference < ConcurrentMap < UUID , Instant > > mapRef = new AtomicReference<>( new ConcurrentHashMap < UUID , Instant > ()  ) ;

Ten thousand platform threads is likely impractical. Consider using virtual threads in Java 21+ if appropriate. Or refactor to submit ten thousand tasks to an executor service.

Your code producing values for the map would do this:

mapRef.get().put( UUID.randomUUID() , Instant.now() ) ;

Your housekeeping chore, where every second you dump the contents of the map, would be a Runnable/Callable task that runs repeatedly in a ScheduledExecutorService (or the managed equivalent in a Jakarta EE server).

final ScheduledExecutorService ses = Executors. … ;

Be sure to shutdown your executor service before your app exits. See the boilerplate code given to you on ExecutorService Javadoc.

Your task would simply replace the map.

ConcurrentMap < UUID , Instant > newMap = new ConcurrentHashMap < UUID , Instant > () ;
ConcurrentMap < UUID , Instant > oldMap = mapRef.getAndSet( newMap ) ;
System.out.println( oldMap ) ;