等待并通知控制器工作者同步

时间:2016-08-20 15:30:00

标签: java multithreading synchronization

我正在努力学习使用wait并通知。

我需要一个应用程序,每10秒向用户询问线程是否必须继续工作。 如果不是(用户按下n),则线程必须等到用户在控制台上写“y”。

我必须使用等待和通知,但我不知道如何。

我正在尝试在没有用户提示的情况下实现wait和notify。

这是创建两个线程的主类,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();
        }
    }
}

问题是它打印“已启动”然后等待永远不会发出的通知!为什么呢?

2 个答案:

答案 0 :(得分:1)

这里发生的事情是你的notify正在运作,但它不会做任何其他事情而不只是"醒来"另一个线程,直到它回到等待,然后控制线程完成,所以它永远不会醒来"第二个线程。

基本上,如果您不想编写用户输入部分,可以使用

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

在这种情况下,剩下的问题是当你通知你的其他线程时,没有任何事情可以完成。所以你需要两件事:

  1. 设置"标志"某处,所以例如将共享布尔值传递给两个线程。你的控制线程应该将布尔设置为true以告诉其他线程它应该停止
  2. 阅读"标志"每次他被唤醒时,从你的工人线程,检查他是否应该停止
  3. 所以你应该做的修改:

    1. 在main方法中创建一个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 );
      
    5. 值得注意的是,为了实现简单的工人 - 控制器关系,其中通信仅限于停止工作线程,您不需要waitnotify。您可以让控制器线程使用t.interrupt()

      中断工作线程

答案 1 :(得分: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();
            }

        }
    }
}