java - ConcurrentLinkedQueue 与 wait() 和 notify()

标签 java concurrency wait notify java.util.concurrent

我不精通多线程。我正在尝试通过一个生产者线程重复截取屏幕截图,该线程将 BufferedImage 对象添加到 ConcurrentLinkedQueue 并且消费者线程将为 poll 队列>BufferedImage 对象将它们保存在文件中。我可以通过重复轮询(while 循环)来使用它们,但我不知道如何使用 notify()wait() 来使用它们。我曾尝试在较小的程序中使用 wait()notify,但无法在此处实现。

我有以下代码:

class StartPeriodicTask implements Runnable {
    public synchronized void run() {
        Robot robot = null;
        try {
            robot = new Robot();
        } catch (AWTException e1) {
            e1.printStackTrace();
        }
        Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit()
                .getScreenSize());
        BufferedImage image = robot.createScreenCapture(screenRect);
        if(null!=queue.peek()){
            try {
                System.out.println("Empty queue, so waiting....");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else{
            queue.add(image);
            notify();
        }
    }
}

public class ImageConsumer implements Runnable {
        @Override
        public synchronized void run() {
            while (true) {
                BufferedImage bufferedImage = null;
                if(null==queue.peek()){
                    try {
                        //Empty queue, so waiting....
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else{
                    bufferedImage = queue.poll();
                    notify();
                }
                File imageFile = getFile();
                if (!imageFile.getParentFile().exists()) {
                    imageFile.getParentFile().mkdirs();
                }
                    try {
                        ImageIO.write(bufferedImage, extension, imageFile);
                        //Image saved
                    catch (IOException e) {
                        tracer.severe("IOException occurred. Image is not saved to file!");
                    }
                }
            }

以前我有一个重复的轮询来检查是否存在 BufferedImage 对象。现在,我已将 run 方法更改为 synchronised 并尝试实现 wait()notify()。我做得对吗?请帮忙。谢谢。

最佳答案

您为作业使用了错误的 QueueConcurrentLinkedQueue 是一个非阻塞队列,这意味着没有生产者消费者语义。如果您只是做一个读者和一个作者,请看一下 SynchronousQueue

简单地说,你的代码可以这样重写

BlockingQueue<?> queue = new SynchrnousQueue<?>();
class StartPeriodicTask implements Runnable {
    public void run() {
        Robot robot = null;
        try {
            robot = new Robot();
        } catch (AWTException e1) {
            e1.printStackTrace();
        }
        Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit()
                .getScreenSize());
        BufferedImage image = robot.createScreenCapture(screenRect);
        queue.offer(image); //1
}
public class ImageConsumer implements Runnable {
        @Override
        public void run() {
            while (true) {
                BufferedImage bufferedImage = queue.poll(); //2

                File imageFile = getFile();
                if (!imageFile.getParentFile().exists()) {
                    imageFile.getParentFile().mkdirs();
                }
                    try {
                        ImageIO.write(bufferedImage, extension, imageFile);
                        //Image saved
                    catch (IOException e) {
                        tracer.severe("IOException occurred. Image is not saved to file!");
                    }
            }

原来如此。

让我解释一下。在//1 行,生产线程会将图像“放置”到队列中。我引用 place 是因为 SynchrnousQueue 没有深度。实际发生的是线程告诉队列“如果有任何线程从这个队列中请求一个元素,那么给它那个线程,让我继续。如果没有,我会等到另一个线程准备好”

行//2 类似于 1,其中消费线程只是等待直到线程提供。这对于单读者单作者来说效果很好

关于java - ConcurrentLinkedQueue 与 wait() 和 notify(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8825762/

相关文章:

java - 代理身份验证失败错误

java - 如何解决相互身份验证的 TLSv1 握手问题?

concurrency - 在达到超时之前如何读取 UDP 连接?

concurrency - Perl 6 中是否有快速并行 "for"循环?

c# - Microsoft 代码片段等待 System.Threading.Thread 完成

java - 参数化内连接

java - 如何将 token 添加到 HttpPost Json 消息

java - 如何正确让多个线程访问共享缓冲区

angularjs - Angular 等待 $http 调用执行下一个函数

c# - 函数等待其他应用程序的响应