我编写了一个专门用于截取屏幕截图并将其转换为jpg的线程。所以我的其他线程可以在下一个屏幕截图时将此屏幕截图与另一台计算机并行发送。到现在为止还挺好。直到我添加了一个System.out.println ... screenshot_ready ...它才能拍摄新的截图。这真的很奇怪,因为println不应该影响线程。
你能否解释为什么它只适用于这个system.out.println?
public void run(){
while(continueLoop){
System.out.println("screenshot_ready: " + screenshot_ready + "\n");
if(!screenshot_ready){
try {
temp = getImageAsJPEG(robot.createScreenCapture(rectangle));
screenshot_ready = true;
System.out.println("screenshot created");
} catch (ImageFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public byte[] returnJPG() {
screenshot_ready = false;
return temp;
}
答案 0 :(得分:1)
如评论中所述,使用没有正确的线程安全结构的多个线程可能会导致意外行为,包括在某些情况下运行时没有可见错误。
在你的情况下,它是System.out
打印流内部的内部同步,它对写入线程(创建屏幕截图的线程)有副作用,使程序看起来像你想要的那样。
然而,由于不清楚是什么让阅读线程看起来做正确的事情,整个程序运行在薄冰上。最轻微的改变可能会破坏它。而且改变甚至不需要在您的程序中!。
由于您的程序旨在将数据从一个线程移交给另一个线程,因此SynchronousQueue
将是一个不错的选择。与真实队列不同,它在两个线程场景中就像一个简单的变量。但是作为BlockingQueue
,它也解决了程序的其他缺陷,例如在CPU消耗循环中轮询变量或者可能多次写入相同的屏幕截图。
final SynchronousQueue<byte[]> data=new SynchronousQueue<>();
public void run(){
while(continueLoop) try {
data.put(getImageAsJPEG(robot.createScreenCapture(rectangle)));
} catch (ImageFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException ex) {
if(continueLoop) ex.printStackTrace();
}
}
public byte[] returnJPG() throws InterruptedException {
return data.take();
}