JAVA:提交给ExecutorService和ExecutorService外部的线程的Callables之间的执行顺序

时间:2014-09-17 22:29:57

标签: java multithreading jms threadpool java.util.concurrent

我构建的简化版本具有以下内容:

  1. 包含线程的线程池(ExecutorService),每个线程都有
    • 将请求消息发送到服务器
    • 通过不断检查共享数据结构等待填写请求
  2. 在这个线程池之外,我有一个MessageListener线程
    • 收听服务器。
    • 一旦请求被填满,它将在共享数据结构中引发“标志”
    • 前面提到的池中的线程会注意到这一点。因此,继续完成自己。
  3. 我发现MessageListener线程仅在ExecutorService终止后执行,而不是与它同时运行,即ExecutorService中的线程阻止MessageListener线程运行。这对我来说显然是不可取的。

    我想知道是否有人可以向我提供一些指示,说明我的结论是否有效,如果是,为什么?什么是解决它的好方法。

    我在下面粘贴了一些半psudeo代码以进一步解释。

    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;
    }
    

1 个答案:

答案 0 :(得分:0)

我在你的代码中看到两个错误:

1)您没有同步对shared_data的访问权限,因此您不会对数组执行原子读取和写入操作,这将导致无法预测的结果。对共享阵列的任何访问都应在synchronized(shared_data) { }块内,或使用同步getSharedData(int i)setSharedData(int i, boolean value)方法更方便

2)MyTask.run()中的等待循环也不是正确的。它的实现方式,如果布尔标志不为真,那么任务将系统地等到超时到期,然后报告任务完成,而实际上它并不知道任务完成。 相反,你应该做这样的事情:

long start = System.currentTimeMillis();
long elapsed = 0L;
boolean flag = false;
while (!(flag = getSharedData(_idx)) &&
  ((elapsed = System.currentTimeMillis() - start) < TIME_OUT)) {
  Thread.sleep(1L);
}
if (flag) {
  // handle completion
} else {
  // handle timeout expired
}