Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
0 / 0 / 0
Регистрация: 22.05.2013
Сообщений: 5

Потоки: как правильно работать с wait(), notify() и synchronized() на примере задачи?

12.04.2014, 21:43. Показов 3435. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Задача: Есть производитель машин - Factory. Есть потребитель - Dealer. Они работают в двух потоках над общим складом. Factory производит и кладет машины в Storage, а Dealer достает.

Проблема: Dealer не запускается, пока Factory не заполнит весь склад. Аналогично, Factory не начнет работать, пока Dealer не заберет все машины из склада.

Нужно: Чтобы потоки запускались работали одновременно, а не поочередно.
Не могу найти баг в своем коде, выкладываю, все что есть. Заранее спасибо.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Main {
    public static void main(String[] args) {
        Factory factory = new Factory();
        Dealer dealer = new Dealer();
 
        Storage storage = new Storage();
        
        factory.setStorage(storage);
        dealer.setStorage(storage);
 
        factory.start();
        dealer.start();
 
        try {
            factory.join();
            dealer.join();
        } catch (InterruptedException e) {
            System.out.println("error in join");
            return;
        }
    }
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Factory extends Thread {
    private int id = 0;
    private Storage storage;
 
    public void setStorage(Storage storage){
        this.storage = storage;
    }
 
    @Override
    public void run() {
        while (true){
 
            synchronized (storage){
                try {
                    while (storage.isFull()){
                        System.out.println("Factory is full");
                        storage.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                id++;
                Car car = new Car();
                car.setId(id);
                storage.addCar(car);
                storage.notify();
                System.out.println("Added new Car with ID = "+id);
            }
 
        }
 
    }
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Dealer extends Thread {
    private Storage storage;
 
    public void setStorage(Storage storage){
        this.storage = storage;
    }
 
    @Override
    public void run() {
        while (true){
 
            synchronized (storage){
                try {
                    while (storage.isEmpty()){
                        System.out.println("Storage is empty");
                        storage.wait();
 
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Car car = storage.getCar();
                storage.notify();
                System.out.println("Car with ID = "+car.getId()+" was bought");
            }
        }
 
    }
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.LinkedList;
import java.util.Queue;
 
public class Storage {
    private Queue<Car> queue = new LinkedList<Car>();
    private static final int maxSize = 500;
 
    public void addCar(Car car){
        queue.add(car);
    }
    public Car getCar(){
        return queue.poll();
    }
    public boolean isFull(){
        return (queue.size() >= maxSize);
    }
    public boolean isEmpty(){
        return queue.isEmpty();
    }
 
}
Java
1
2
3
4
5
6
7
8
9
public class Car {
    private int id = 0;
    public void setId(int id) {
        this.id = id;
    }
    public int getId(){
        return id;
    }
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.04.2014, 21:43
Ответы с готовыми решениями:

Зачем synchronized вокруг wait/notify?
Добрый день! Хочу прояснить свое понимание в данном вопросе. На сколько мне известно synchronized позволяет только одному потоку...

Потоки. Wait, notify
Нужно создать программу, реализующую работу с потоками с помощью wait, notify. Когда два потока обращаются к одному файлу по очереди для...

Почему notify не заканчивается без synchronized?
Здравствуйте. Дан код public class exer21 { public static void main(String args) throws InterruptedException { ...

4
 Аватар для IVIakCollideR
40 / 40 / 14
Регистрация: 26.12.2013
Сообщений: 309
12.04.2014, 21:50
ошибки вылазят, или в чем проблема?
0
0 / 0 / 0
Регистрация: 22.05.2013
Сообщений: 5
12.04.2014, 21:55  [ТС]
IVIakCollideR, Ошибки не вылазят, все работает. Сначала поток Factory полностью заполняет Storage, а только потом поток Diler начинает доставать из Storage объекты. А должно как-то одновременно это происходить, когда в Storage появляются объекты Diler их сразу достаёт, а не ждёт пока Factory заполнит весь Storage.
0
 Аватар для IVIakCollideR
40 / 40 / 14
Регистрация: 26.12.2013
Сообщений: 309
12.04.2014, 22:23
правильно, у вас стоит общий лок, и он освободиться лишь в том случае в потоке фактори, когда она полностью заложит склад, то есть пока не вызовет wait() который отдаст управление

Добавлено через 1 минуту
попробуйте создать 2 лок обьекта

Добавлено через 10 минут
а нет, извиняюсь, у тебя же обязательно с нотифаями, тогда 2 разных лока не проканает

Добавлено через 10 минут
как то вообще тогда условие задачи не соответствует тому что вы сделали.
Я бы немного переписал синхронайз блоки Dealer и фактори
Дилер:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Dealer extends Thread {
    private Storage storage;
 
    public void setStorage(Storage storage){
        this.storage = storage;
    }
 
    @Override
    public void run() {
        while (true){
 
            synchronized (storage){
             
                if(!storage.isEmpty()){    
                Car car = storage.getCar();    
                System.out.println("Car with ID = "+car.getId()+" was bought");
                storage.notify();
                try {
                    storage.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   
            }
                
        }
 
    }
    }
}
Фабрика
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Factory extends Thread {
    private int id = 0;
    private Storage storage;
 
    public void setStorage(Storage storage){
        this.storage = storage;
    }
 
    @Override
    public void run() {
        while (true){
 
            synchronized (storage){
 
                id++;
                Car car = new Car();
                car.setId(id);
                storage.addCar(car);
                storage.notify();
                System.out.println("Added new Car with ID = "+id);
                
                try {
                    storage.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
 
        }
 
    }
}
0
0 / 0 / 0
Регистрация: 22.05.2013
Сообщений: 5
13.04.2014, 11:12  [ТС]
Спасибо за ответ
Но это не совсем то. Если на складе кончатся машины, то Diler превращается в холостой цикл while, что не есть тру. И теперь всё блокируется по поводу и без повода каждый раз, потому что wait так расставлен.
А еще wait не как не предохранится от spurious wakeup

Добавлено через 1 час 24 минуты
Проблема нашлась. Всё работало корректно, только каждый поток успевал либо полностью заполнить, либо полностью опустошить склад. Если добавить sleep'ы в при создании и забирании товара, то всё работает как нужно.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Factory extends Thread {
    private int id = 0;
    private Storage storage;
 
    public void setStorage(Storage storage){
        this.storage = storage;
    }
 
    @Override
    public void run() {
        while (true){
            try {
                sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (storage){
                try {
                    while (storage.isFull()){
                        System.out.println("Factory is full");
                        storage.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                id++;
                Car car = new Car();
                car.setId(id);
                storage.addCar(car);
                System.out.println("Added new Car with ID = "+id);
                storage.notify();
            }
 
        }
 
    }
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Dealer extends Thread {
    private Storage storage;
 
    public void setStorage(Storage storage){
        this.storage = storage;
    }
 
    @Override
    public void run() {
        while (true){
            try {
                sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (storage){
                try {
                    while (storage.isEmpty()){
                        System.out.println("Storage is empty");
                        storage.wait();
 
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Car car = storage.getCar();
                System.out.println("Car with ID = "+car.getId()+" was bought");
                storage.notify();
            }
        }
 
    }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
13.04.2014, 11:12
Помогаю со студенческими работами здесь

Многопоточность. wait(), notify()
Здравствуйте, в Шилдте есть пример: //Правильная реализация поставщика и потребителя package PCFixed; class Q { int n; ...

Синхронизация. Wait(). Notify().
Задание-1 поток в цикле увеличивает значение переменной, другой печатает это значение. Проблема-выполняется только первая итерация....

Методы wait() и notify()
class Blocked { public synchronized void doWait() { try { System.out.print(&quot;Не &quot;); this.wait();...

Синхронизация потоков wait и notify
Народ помогите понять. Делаю два анонимных внутренних класса. Суть в том что второй анонимный класс находиться в ожидании, а первый когда...

Обращение к файлу. wait(), notify(), notifyAll(), Runnable
&quot;Продемонстрировать программу, в которой разные потоки обращаются к файлу, используя методы wait(), notify(), notifyAll(). Для разработки...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru