Как уведомить все потоки в классе в JAVA? - PullRequest
2 голосов
/ 14 января 2020

Могу ли я сделать функцию stati c, которая уведомляет все потоки, которые ожидают в любом экземпляре этого класса?

(Логика c здесь состоит в том, что у меня есть очереди, в которых ожидают потоки потому что они пусты, и я хочу завершить sh запуск программы при вызове этой функции)

queue = new Vector<T>();

 public synchronized T extract(){
        while(queue.isEmpty())
            try {
                this.wait();
                if(!active) {return null;}
            }catch(InterruptedException e) {}
        T t = queue.elementAt(0);
        queue.remove(0);
        return t;
}

Это метод извлечения. когда очередь пуста, потоки go ждут. Я хочу сделать логическое значение «активным» равным false и notifyAll.

Тогда я позабочусь, чтобы потоки больше не вызывали этот метод

1 Ответ

3 голосов
/ 14 января 2020

Логика c здесь заключается в том, что у меня есть очереди, в которых ожидают потоки, потому что они пусты, и я хочу завершить sh запуск программы при вызове этой функции

IMO, лучшим решением вашей проблемы будет продолжение использования блокировок для каждого экземпляра, но отправка ядовитых пилюль в каждую очередь, когда придет время закрыть их все.

final T poison_pill = new T(...);

public synchronized T extract(){
    while(queue.isEmpty())
        try {
            this.wait();
        }catch(InterruptedException e) {}
    T t = queue.elementAt(0);
    if (t == poison_pill) {
        ...My preference would be to raise an exception here, but...
        return NULL;              // ...this was in your original example.
    }
    else {
        queue.remove(0);
        return t;
    }
}

Если вы действительно хотите иметь возможность notify() всех различных экземпляров одновременно, то вам придется сделать их все wait() на тот же объект глобальной блокировки.

final Object global_lock = new Object();

public T extract(){
    synchronized(global_lock) {
        while(queue.isEmpty())
            try {
                global_lock.wait();
                if(!active) {return null;}
            }catch(InterruptedException e) {}
        T t = queue.elementAt(0);
        queue.remove(0);
        return t;
    }
}

А потом еще где-нибудь:

synchronized(lock) {
    ...
    global_lock.notifyAll();
}
...