Java concurrency – Multiple queue monitors

At work, I’ve implemented a queue monitor batch application. Due to business rule changes, it now needs to monitor two queues. Instead of creating another batch application, I really wanted to stick with the same application but just create two threads, each monitoring its own queue.

However, the twist I need is to have the main batch application thread die as soon as either queue monitoring thread dies.

I’ve been searching for a graceful way to handle such a concurrency need in Java. Thank you to Gary Myers, I’ve got a great start on it.

The basic idea is to pass a java blocking queue to both of the threads and if either thread fails, do blockingQueue.offer to indicate so. Then in the main thread, it will check for the blocking queue’s result. blockingQueue.take() blocks/waits for it to return and then continues the execution of the main thread.

Things I learned that made today AMAZING!

Put repositories in the pom.xml instead of settings.xml for maven to look through multiple repositories

Use SynchronousQueue to ensure only 1 element at a time may exist in the queue

Use daemon to make sure the JVM will die even if there is a thread running

You can EMBED ActiveMQ using spring so you don’t have install it at all

Below is a simple concurrency example that demonstrates the idea from Gary Myers.

Worker:

public class Worker implements Runnable {
private BlockingQueue<String> finishedQueue;
private String result;
private long sleepTime;
public Worker(BlockingQueue<String> finishedQueue, String result, long sleepTime) {
this.finishedQueue=finishedQueue;
this.result=result;
this.sleepTime=sleepTime;
}
public void run() {
try {
TimeUnit.SECONDS.sleep(sleepTime);
finishedQueue.offer(result); //you have to use offer to get this queue to work. It will throw an exception if there is something in the queue.
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}

DaemonThreadFactory:

public class DaemonThreadFactory implements ThreadFactory {
private AtomicInteger counter;
public DaemonThreadFactory() {
this.counter=new AtomicInteger(0);
}
public Thread newThread(Runnable r) {
Thread thread=new Thread(r);
//if you wanted you can make this class generic by having the constructor take arguments that can be used to configure the following
thread.setDaemon(true); //need it to be daemon so the JVM will die even if there is a thread running
thread.setName("Daemon Thread: " + counter.incrementAndGet()); //you don't have to give it a name, but I always do.
return thread;
}
}

Test the threads in a simple example:

public class Main {
public static void main(String[] args) throws InterruptedException {
ExecutorService service=Executors.newFixedThreadPool(2, new DaemonThreadFactory());
SynchronousQueue<String> queue=new SynchronousQueue<String>(); //this queue can hold 1 element at a time, so basically the first thread to finish will be the one to successfully put the element in the queue
//create the runnables before hand so that extra time isn't spent instantiating the runnables at submission time.
Runnable runnable1=new Worker(queue, "Runnable 1", 4);
Runnable runnable2=new Worker(queue, "Runnable 2", 3);
service.execute(runnable1);
service.execute(runnable2);
System.out.println("before queue");
System.out.println(queue.take());
System.out.println("after queue");
service.shutdown();
}
}

I will not go into the details of the code I added for queue monitoring as they are a lot more involved.

The coolest thing I learned about ActiveMQ is how you can embed it using the following spring configuration: