在下面的代码中,在非常罕见的情况下(QueueThread对象执行了3亿次)它到达下面提到的if块和queue.size结果是7999.可能的原因是什么。
if(q.size()<batchsize){
System.out.println("queue size" +q.size());
}
基本上它无法执行queue.add语句,但执行线程中的所有其他语句。
代码段如下。
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class CLinkQueueTest {
public static final int itersize=100000;
public static final int batchsize=8000;
public static final int poolsize=100;
public static void main (String args[]) throws Exception{
int j= 0;
ExecutorService service = Executors.newFixedThreadPool(poolsize);
AtomicInteger counter = new AtomicInteger(poolsize);
ConcurrentLinkedQueue<String> q = new ConcurrentLinkedQueue<String>();
String s ="abc";
while(j<itersize){
int k=0;
while(k<batchsize){
counter.decrementAndGet();
service.submit(new QueueThread(counter, q, s));
if(counter.get()<=0){
Thread.sleep(5);
}
k++;
}
if(j%20 ==0){
System.out.println("Iteration no " + j);
}
while(counter.get() < poolsize){
//wait infinitely
}
if(q.size()<batchsize){
System.out.println("queue size" +q.size());
}
q.clear();
j++;
}
System.out.println("process complete");
}
import java.util.Queue;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class QueueThread implements Callable<Boolean> {
private AtomicInteger ai;
private Queue<String> qu;
private String st;
public QueueThread(AtomicInteger i, Queue<String> q, String s){
ai = i;
qu = q;
st = s;
}
@Override
public Boolean call() {
try{
qu.add(st);
} catch(Throwable e){
e.printStackTrace();
}finally{
ai.incrementAndGet();
}
return true;
}
}
答案 0 :(得分:0)
可能是因为Executor还没有完成处理,有一次它在队列中注册一个太少的条目了吗?
很明显,每次调用QueueThread.call()
时,都会添加队列,AtomicInteger
会递增。我只能想到一个call
尚未执行。
也许你可以通过使用类似的东西对系统有点好处:
while(counter.get() < poolsize){
//wait infinitely
Thread.currentThread().sleep(5);
}
但这只是我的意见。
答案 1 :(得分:0)
ConcurrentLinkedQueue.size
方法的文档说:
请注意,与大多数集合不同,此方法不是恒定时间操作。由于这些队列的异步性质,确定当前元素数需要O(n)遍历。 此外,如果在执行此方法期间添加或删除元素,则返回的结果可能不准确。因此,此方法在并发应用程序中通常不是很有用。