A simplified version of what I am build has the following:
- A pool of threads (an ExecutorService), containing threads, each of which
- Sends an request message onto a server
- Waits for a the request fullfiled by continous checking on a shared data structure
- Outside of this thread pool, I have a MessageListener thread that
- listens to the server.
- Once the request is fufiled, it will raise a 'flag' in the shared data structure
- Thread in in the pool previously mentioned will notice this. And hence continue to complete itself.
I found that the MessageListener thread is ONLY executed AFTER the ExecutorService is terminated, not running concurrently with it, i.e. threads in the ExecutorService are blocking the MessageListener thread from running. This is obviously undesirable for my purpose.
I wonder if someone can provide me with some pointers that whether my conclusion is valid and if so, why? and what is a good approach to get around it.
I pasted some semi-psudeo code below to further explain.
public static final int NUM_TASK = 10;
public static final int TIME_OUT = 5000;
public static boolean[] shared_data = new boolean[NUM_TASK];
public static void main(String[] args) throws InterruptedException{
// CREATE the receiver which will be set as an LISTENER for a JMS consumer queue that
// later the tasks in the Executor Service will send request to
setupJMSProducerConsumer();
// CREATE the Executor Service (pool)
ExecutorService fixThreadPoolES = Executors.newFixedThreadPool(10);
List<Future<String>> futures = new ArrayList<Future<String>>();
for(int i = 0; i < NUM_TASK; i++){
// Submit a Callable task to Replay the file
MyTask task = new MyTask(i);
futures.add(fixThreadPoolES.submit(task));
}
// GATHER the result here, based on futures
// gatherResult(futures);
// TERMINATE the ExecutorService
fixThreadPoolES.shutdown();
fixThreadPoolES.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
private static class MyTask implements Callable<String> {
private static final int WAIT_TIME_SLOT = 1000;
int _idx = -1;
public MyTask (int idx){
_idx = idx;
}
@Override
public String call() throws Exception {
return run();
}
private String run() throws InterruptedException{
// SEND request
// sendRequest(_idx);
// WAIT until the corresponding result in the shared data is set to 'true' by the corresponding LISTENER
int timeWaited = 0;
while (getSharedData(_idx) != true){
timeWaited += WAIT_TIME_SLOT;
Thread.sleep(WAIT_TIME_SLOT);
if (timeWaited > TIME_OUT){
return "Listener timed out, flag not raised, task incompleted for: " + _idx;
}
}
return "Listener raised the flag, task completed for: " + _idx;
}
}
public static class MyMsgReceiver implements MessageListener{
@Override
public void onMessage(Message msg) {
String msgTxt = null;
try {
msgTxt = ((javax.jms.TextMessage) msg).getText();
} catch (JMSException e) {
e.printStackTrace();
return;
}
for (int i = 0; i < NUM_TASK; i++){
if (msgTxt.contains(String.valueOf(i))){
setSharedData(i, true);;
};
}
}
}
private static void setupJMSProducerConsumer(){
com.tibco.tibjms.TibjmsConnectionFactory factory = new com.tibco.tibjms.TibjmsConnectionFactory(TIBCO_URL);
Connection connection = factory.createConnection(TIBCO_USER, TIBCO_PASS);
Session session = connection.createSession(false, 24);
MessageConsumer consumer = session.creatConsumer(session.createQueue(QUEUE_NAME));
MyMsgReceiver receiver = new MyMsgReceiver();
consumer.setMessageListener(receiver);
}
public static synchronized boolean getSharedData(int idx) {
return shared_data[idx];
}
public static synchronized void setSharedData(int idx, boolean val) {
shared_data[idx] = val;
}