gpt4 book ai didi

java - 即使条件为假,Java线程也会进入条件

转载 作者:行者123 更新时间:2023-12-03 13:15:57 25 4
gpt4 key购买 nike

我目前正在尝试编写一个将客户发送到最短队列的应用程序。每个队列都有其自己的线程。
在Queue类中,我有一个实例变量nrClients,用于跟踪队列中有多少个客户端。

在run方法中,我有一个while条件,仅当nrClients大于0时才使线程保持运行,但是有时即使nrClients为0,它也会进入while循环,从而在while内的代码中触发了NullPointerException。我也有一个for循环,它从0变为nrClients-1,但是有时它会进入该循环并给我一个Index 0 out of bounds for length 0异常。这是我在该类中编写的代码:

public class Queue implements Runnable{
BlockingQueue<Client> queue;
private int nrClients;
private AtomicInteger waitTime;
private boolean isClosed=true;

public Queue(){
nrClients= 0;
waitTime = new AtomicInteger(0);
queue = new LinkedBlockingQueue<Client>();
}

public void addClient(Client c){
nrClients++;
queue.add(c);
waitTime.addAndGet(c.getServiceTime());
c.setWaitTime(waitTime.get());
}

private void removeClient(Client c){
nrClients--;
queue.remove();
}

@Override
public void run() {
while (nrClients>0) {
isClosed = false;
Client c = queue.peek();
try {
int mustWait = c.getServiceTime();
for (int i = 0; i < mustWait; i++) {
Thread.sleep(10);
c.decServiceTime();
waitTime.decrementAndGet();
}

} catch (InterruptedException e) {
}
removeClient(c);
}
if (nrClients == 0)
isClosed = true;
}

public AtomicInteger getWaitTime() {
return waitTime;
}

public String toString(){
if(nrClients==0){
return "closed";
}
else
{
String r="";
for(int i=0; i<nrClients; i++){
Client c = (Client) queue.toArray()[i];
r+="("+c.getID()+","+c.getArrivalTime()+","+c.getServiceTime()+"); ";
}
return r;
}
}

public boolean isClosed() {
return isClosed;
}

我似乎找不到导致这些异常的问题,如果您能指出问题所在,我将不胜感激。先感谢您!

编辑:我试图使nrClients volatile /AtomicInteger,都没有解决问题。另外,通过用queue.size()替换nrClients,我仍然在toString方法中包含的for循环中获得了索引异常。

最佳答案

如果其他线程调用addClient,则在将nrClient对象添加到c之前,将queue增加,然后增加。如果while循环恰好在此时运行,则nrClient为1,但queue仍然为空。

您需要使用访问synchroniseaddClient的方式对nrClient方法进行queue(一种实现方法是通过实现方法getNrClient(),然后方法getNrClientaddClient都是具有共同synchronized(lock)Object lock = new Object())。

更好:避免一起使用nrClient。而是检查queue.peek是否不为null或使用poll。

for循环中的queue.size()问题类似,您在不同时间调用queue.size()和queue.toArray(),因此它们可能不一致。而是:在for循环外获取数组,并使用array.length。

关于java - 即使条件为假,Java线程也会进入条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60917465/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com