[英]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: 我正在构建的简化版本具有以下内容:
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.