简体   繁体   English

JAVA:提交给ExecutorService的可调用对象与ExecutorService之外的线程之间的执行顺序

[英]JAVA: Execution Order between Callables submitted to ExecutorService and Threads Outside of the ExecutorService

A simplified version of what I am build has the following: 我正在构建的简化版本具有以下内容:

  1. A pool of threads (an ExecutorService), containing threads, each of which 线程池(ExecutorService),包含线程,每个线程
    • Sends an request message onto a server 将请求消息发送到服务器
    • Waits for a the request fullfiled by continous checking on a shared data structure 通过连续检查共享数据结构来等待请求已满
  2. Outside of this thread pool, I have a MessageListener thread that 在此线程池之外,我有一个MessageListener线程,
    • 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, ie threads in the ExecutorService are blocking the MessageListener thread from running. 我发现MessageListener线程仅在ExecutorService终止后才执行,而不是与其并发运行,即ExecutorService中的线程阻止了MessageListener线程运行。 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;
}

I see two things wrong in your code: 我发现您的代码中有两件事是错误的:

1) You don't synchronize the access to shared_data , therefore you're not performing atomic reads and writes to the array and this will lead to unpredicatble results. 1)您不同步对shared_data的访问,因此您没有对数组执行原子读取和写入操作,这将导致不可预测的结果。 Any access to the shared array should be within a synchronized(shared_data) { } block, or more conveniently using synchronized getSharedData(int i) and setSharedData(int i, boolean value) methods 对共享数组的任何访问都应在getSharedData(int i) synchronized(shared_data) { }块内,或更方便地使用同步的getSharedData(int i)setSharedData(int i, boolean value)方法

2) the wait loop in MyTask.run() isn't quite right either. 2) MyTask.run() )中的等待循环也不完全正确。 The way it's implemented, if the boolean flag isn't true, then the task will systematically wait until the timeout expires, then report completion of the task, when in fact it doesn't know that the task is completed. 它的实现方式是,如果boolean标志不为true,则任务将系统地等待直到超时到期,然后报告任务完成,而实际上却不知道任务已完成。 Instead, you should do something like this: 相反,您应该执行以下操作:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM