Ждите и уведомляйте как контроллер-рабочий синхронизации

java multithreading synchronization

169 просмотра

2 ответа

Я пытаюсь научиться использовать ждать и уведомлять.

Мне нужно приложение, которое каждые 10 секунд спрашивает пользователя, должен ли поток продолжать работать или нет. Если нет (пользователь нажимает n), поток должен ждать, пока пользователь не напишет «y» на консоли.

Я должен использовать ожидание и уведомить, но я не знаю, как это сделать.

Я пытаюсь реализовать ожидание и уведомление без приглашения от пользователя.

Это основной класс, который создает два потока, FolderThread - это поток, который должен работать, а ControlThread - тот, кто должен спрашивать пользователя, хочет ли он продолжить или нет.

public class MainClass {

    public static void main(String[] args) throws InterruptedException {
        FolderThread folder = new FolderThread();
        Thread t = new Thread(folder);
        ControlThread control = new ControlThread(folder);
        Thread t2 = new Thread(control);
        t.start();
        t2.start();
    }
}

FolderThread

public class FolderThread implements Runnable {

    @Override
    public void run() {
        while(true) {
            System.out.println("started");
            synchronized(this) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

ControlThread

public class ControlThread implements Runnable {

    FolderThread folder;

    public ControlThread (FolderThread folder) {
        this.folder = folder;
    }

    @Override
    public void run() {
        synchronized(folder) {
            folder.notify();
        }
    }
}

Проблема в том, что он печатает «Запущено», а затем ждет уведомления, которое никогда не придет! Почему?

Автор: untruste Источник Размещён: 08.11.2019 11:30

Ответы (2)


1 плюс

Решение

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

По сути, если вы не хотите писать пользовательскую часть ввода, вы можете смоделировать с помощью

Thread.sleep(2000);
// and then do what would be done if the user had type 'y'

В этом случае остающаяся проблема заключается в том, что когда вы уведомляете другой поток, ничего не делается. Итак, вам нужно 2 вещи:

  1. установите где-нибудь «флаг», например, передайте общий Boolean в оба потока. ваш управляющий поток должен установить для этого логического значения значение true, чтобы сообщить другому потоку, что он должен остановиться
  2. читайте "флаг" из вашего рабочего потока каждый раз, когда он просыпается, чтобы проверить, должен ли он остановиться или нет

Итак, модификации, которые вы должны сделать:

  1. Создайте AtomicBoolean в основном методе:

    AtomicBoolean flag = new AtomicBoolean();
    
  2. Передайте этот AtomicBoolean конструкторам обоих потоков:

    FolderThread folder = new FolderThread(flag);
    ControlThread control = new ControlThread(folder, flag);
    

    Конечно, вам нужно будет адаптировать объявления конструктора.

  3. Получить FolderThread, чтобы проверить флаг, когда он проснется. Заменить while(true)на

    while(flag.get() == false)
    
  4. Получите ControlThread, чтобы обновить флаг, когда он хочет остановить его:

    flag.set( true );
    

Стоит отметить , однако, что для реализации простого отношения работника-контроллер, где связь ограничивается остановкой рабочего потока, вам не нужно waitи notify. Вы можете просто заставить поток контроллера прерывать рабочий поток, используяt.interrupt()

Автор: Vic Seedoubleyew Размещён: 20.08.2016 03:42

0 плюса

Это мое решение (с участием пользователя)

FolderThread

    public class FolderThread implements Runnable {

    @Override
    public void run() {

        while(true) {
            System.out.println("Checking...");

            synchronized(this) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

ControlThread

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ControlThread implements Runnable {

    FolderThread folder;

    public ControlThread (FolderThread folder) {
        this.folder = folder;
    }
    @Override
    public void run() {

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        while(true) {

            InputStreamReader is = new InputStreamReader(System.in);
            BufferedReader br = new BufferedReader(is);

            try {   
                do {
                    System.out.println("Continue? y/n");

                }
                while(br.readLine().equals("n"));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            synchronized(folder) {
                folder.notify();
            }

            try {
                Thread.sleep(10000);
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        }
    }
}
Автор: untruste Размещён: 20.08.2016 05:03
Вопросы из категории :
32x32