gpt4 book ai didi

java - notifyAll() 的多线程问题

转载 作者:太空宇宙 更新时间:2023-11-04 13:53:08 28 4
gpt4 key购买 nike

我正在做一个练习,模拟商店中具有多个线程的等待队列。

我有一个等候名单和 2 个柜台当某个客户端排在等待列表的第一位并且柜台有空闲时,该客户端进入柜台等待2秒,通知其他客户端然后离开。

我不明白为什么等待的客户永远不会收到通知。(我阅读了许多其他主题,但找不到答案)。

package tp;
import java.util.Random;
public class Client extends Thread{

private static Counters counters = new Counters(2);
private static WaitingQueue queue = new WaitingQueue(3);
private static Random random = new Random();
private static Integer client_counter = 1;
private Integer id;

public Client(){
this.id = client_counter++;
}

public static void main(String[] args) {
while (true) {
try {
Thread.sleep(500);
Client client = new Client();
client.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void run() {
boolean end = false;
System.out.printf("Client %d come in the shop\n", this.id);
if (queue.enter(this)) { // false if queue is full
System.out.printf("Client %d go in the waiting queue\n", this.id);
while (!end) {
try {
end = this.waitToEnter();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

private synchronized boolean waitToEnter() throws InterruptedException{
while ( (!queue.isFirst(this))) {
// return true if client is first in the queue
System.out.printf("Client %d wait to be first\n", this.id);
wait();

}
int nb = counters.entrer(this);
// return -1 if no free counter else index of the counter
while (nb == -1) {
System.out.printf("Client %d for a free counter\n", this.id);
wait();
nb = counters.entrer(this);
}
this.enterCounter(nb);
notifyAll();
return true;
}

private void enterCounter(int nb) throws InterruptedException {
queue.leave(this);
System.out.printf("Client %d in counter %d\n", this.id, nb);
this.sleep((long) 2000 + random.nextInt(1000));
System.out.printf("Client %d out of counter %d\n", this.id, nb);
counters.leave(this, nb);
}
}



package tp;

import java.util.ArrayList;

public class Counters {

private ArrayList<Boolean> counters = new ArrayList<Boolean>();

public Counters(int nb_guichets) {
/* Set all counter to free*/
for (int i = 0; i < nb_guichets; i++) {
counters.add(i, true);
}
}

public synchronized int entrer(Client client) {
/* if a counter is free return its index else -1 */
for (int i = 0; i < counters.size(); i++) {
if (counters.get(i)) {
counters.set(i,false);
return i;
}
}
return -1;
}

public void leave(Client client, int nb) {
counters.set(nb, true);
}
}




package tp;
import java.util.ArrayList;

public class WaitingQueue {

public ArrayList<Client> waiting_list = new ArrayList();
private int waiting_list_size;

public WaitingQueue(int size) {
this.waiting_list_size = size;
}

public boolean isEmpty() {

return waiting_list.size() == 0;
}

public boolean isFirst(Client client) {
return waiting_list.get(0).equals(client);
}

public synchronized boolean enter(Client client) {
boolean res = false;
if(waiting_list.size() < waiting_list_size) {
res = waiting_list.add(client);
}
return res;
}

public synchronized void leave(Client client) {
waiting_list.remove(client);
}
}

日志:

Client 1 come in the shop
Client 1 go in the waiting queue
Client 1 in counter 0
Client 2 come in the shop
Client 2 go in the waiting queue
Client 2 in counter 1
Client 3 come in the shop
Client 3 go in the waiting queue
Client 3 for a free counter
Client 4 come in the shop
Client 4 go in the waiting queue
Client 4 wait to be first
Client 5 come in the shop
Client 5 go in the waiting queue
Client 5 wait to be first
Client 1 out of counter 0
Client 6 come in the shop
Client 2 out of counter 1
Client 7 come in the shop
Client 8 come in the shop

最佳答案

waitnotify/notifyall 对它们被调用的对象起作用。您正在创建许多不同的客户端对象,因此每个对象都有自己的监视器。

您可能应该坚持使用 java.util.concurrent 包中的类来进行同步(例如,Semaphore)。

如果您想坚持使用对象同步方法(作为练习),您需要修改代码以拥有一个可供等待和通知的对象。

关于java - notifyAll() 的多线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30104631/

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