我不精通多线程。我正在尝试通过一个生产者线程重复截取屏幕截图,该线程将 BufferedImage
对象添加到 ConcurrentLinkedQueue
并且消费者线程将为
对象将它们保存在文件中。我可以通过重复轮询(while 循环)来使用它们,但我不知道如何使用 poll
队列>BufferedImagenotify()
和 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()
。我做得对吗?请帮忙。谢谢。
最佳答案
您为作业使用了错误的 Queue
。 ConcurrentLinkedQueue
是一个非阻塞队列,这意味着没有生产者消费者语义。如果您只是做一个读者和一个作者,请看一下 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/