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中的
- 将请求消息发送到服务器
- 通过对共享数据结构进行连续检查,等待请求完成
- 侦听服务器李>
- 一旦请求被归档,它将在共享数据结构中升起一个“标志”
- 前面提到的池中的线程将注意到这一点。从而不断完善自身
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){}
块内,或者更方便地使用synchronizedgetSharedData(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);”用于向发送请求