Java线程队列重叠

时间:2015-08-10 10:56:53

标签: java multithreading overlap threadpoolexecutor

我在ThreadPoolExecutor的队列线程中遇到问题。有时它会重叠同一个任务。

以下是我的代码:

int threadSize = 3;
int maxThreadSize = 3;
int TTL = 10;
int queueSize = map.size();


ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(queueSize);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(threadSize, maxThreadSize, TTL, TimeUnit.SECONDS, queue, new ThreadPoolExecutor.CallerRunsPolicy());

for(final Entry<String,String> entry : map.entrySet()){
   threadPool.execute(new Runnable() {                              
      @Override
      public void run() {
         //…do something
         System.out.println(entry.getKey + " : " + entry.getValue);                     
      }
   });
}

例如

如果map有一对密钥和值,如下所示。

  

键:值

     

“1”:“AAA”

     

“2”:“BBB”

     

...

     

“26”:“ZZZ”

我的结果有时可能是......

  

1:AAA

     

2:BBB

     

3:CCC

     

3:CCC

     

4:DDD

     

...

     

25:YYY

它是双“3:CCC”并且没有“26:ZZZ”。 我该如何解决这个问题?

[编辑] 这个问题随机发生,不仅是“3:CCC”

有时会发生在其他条目

有时问题不会发生

当一个条目重叠时意味着另一个条目不会被打印

所以我猜这是我的排队问题

2 个答案:

答案 0 :(得分:0)

您使用的地图怎么样?也许它填满了你没有注意到的地方?

如果您需要查看有序元素,请尝试PriorityQueue

答案 1 :(得分:0)

当您迭代Map.entrySet时,它不必每次都为每个条目返回一个不可变的Entry对象。它可以在迭代期间反复返回相同的Entry对象,修改其字段,或者它可能已经为映射中的每个键值映射分配了Entry对象,但修改了现有的{ {1}}以后修改地图的对象。这意味着Entry个对象在创建每个Entry时在Runnable中使用时可能没有相同的键和值。

尝试创建一个单独的不可变Runnable对象供每个Entry使用:

Runnable

或者将键和值拉入单独的变量,以便在for (Entry<String,String> entry1 : map.entrySet()) { final Entry<String,String> entry = new AbstractMap.SimpleImmutableEntry<>(entry1); /* ... */ }

中使用
Runnable