JAVA:提交给ExecutorService的可调用函数和ExecutorService之外的线程之间的执行顺序

JAVA:提交给ExecutorService的可调用函数和ExecutorService之外的线程之间的执行顺序,java,multithreading,jms,threadpool,java.util.concurrent,Java,Multithreading,Jms,Threadpool,Java.util.concurrent,我正在构建的简化版本包含以下内容: 线程池(ExecutorService),包含线程,每个线程 将请求消息发送到服务器 通过对共享数据结构进行连续检查,等待请求完成 在这个线程池之外,我有一个MessageListener线程 侦听服务器 一旦请求被归档,它将在共享数据结构中升起一个“标志” 前面提到的池中的线程将注意到这一点。从而不断完善自身 我发现MessageListener线程仅在ExecutorService终止后执行,而不是与它同时运行,即ExecutorService中的

我正在构建的简化版本包含以下内容:

  • 线程池(ExecutorService),包含线程,每个线程
    • 将请求消息发送到服务器
    • 通过对共享数据结构进行连续检查,等待请求完成
  • 在这个线程池之外,我有一个MessageListener线程
    • 侦听服务器
    • 一旦请求被归档,它将在共享数据结构中升起一个“标志”
    • 前面提到的池中的线程将注意到这一点。从而不断完善自身
  • 我发现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;
    }
    
    public static final int NUM_TASK=10;
    公共静态最终整数超时=5000;
    公共静态布尔值[]共享_数据=新布尔值[NUM_任务];
    公共静态void main(字符串[]args)引发InterruptedException{
    //创建将被设置为以下JMS使用者队列的侦听器的接收器:
    //稍后,Executor服务中的任务将向发送请求
    setupJMSProducerConsumer();
    //创建执行器服务(池)
    ExecutorService fixThreadPoolES=Executors.newFixedThreadPool(10);
    列表期货=新的ArrayList();
    for(int i=0;i超时){
    return“侦听器超时,未升起标志,任务未完成:”+_idx;
    }
    }
    return“侦听器已升起标志,任务已完成:”+_idx;
    }
    }
    公共静态类MyMsgReceiver实现MessageListener{
    @凌驾
    公共消息无效(消息消息消息){
    字符串msgTxt=null;
    试一试{
    msgTxt=((javax.jms.TextMessage)msg.getText();
    }捕获(JME){
    e、 printStackTrace();
    返回;
    }
    for(int i=0;i
    我发现您的代码中有两处错误:

    1) 您没有同步对
    共享_数据的访问,因此您没有对阵列执行原子读写,这将导致无法预测的结果。对共享数组的任何访问都应该在
    synchronized(shared_data){}
    块内,或者更方便地使用synchronized
    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
    }
    
    long start=System.currentTimeMillis();
    长时间运行=0升;
    布尔标志=假;
    而(!(flag=getSharedData(_idx))&&
    ((已用时间=System.currentTimeMillis()-start)<超时)){
    睡眠(1L);
    }
    国际单项体育联合会(旗){
    //处理完成
    }否则{
    //句柄超时已过期
    }
    
    为什么?未来已经存在。你在这里重新发明了几个轮子。这里根本没有证据表明在执行器之外还有第二条线程。执行器不能阻止该线程,这是不正确的。不完整。嗨,@EJP,很抱歉我在这个简化的伪代码片段中没有说清楚。ExecutorService“外部”有一个线程的方式是通过一个MessageListener“侦听”服务器上的JMS队列。ExecutorService“内部”线程的run()中的“//sendRequest(_idx);”用于向发送请求