我正在编写一个多线程应用程序,用于模拟一个简单的z80机器,我在显示部分遇到问题。我有一个扩展JPanel的Screen类,以及一个DSP类来处理单独线程上的所有视频处理。
使用println()
进行调查后,我确定问题是将结果数据从DSP类复制到Screen类中的帧缓冲区。当DSP写入显示器时,阵列会保留数据,直到需要绘制组件,整个阵列被擦除,屏幕保持黑色。下面是我的Screen类的代码,因为我知道DSP类的运行方式应该如此。评论的打印行是指DSP将所有白色像素写入帧缓冲区。
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.Timer;
/**
*
* @author James
*/
public class Screen extends JPanel{
private int[] memory = new int[153600];
private int location = 0;
private boolean writing;
private BufferedImage img;
private Timer timer;
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
int index = 0;
for(int x = 319; x > 0; x--){
for(int y = 1; y < 240; y ++){
System.out.println(memory[index + 1]); // always prints zero
int color = (memory[index] + (memory[index + 1] * 256));
img.setRGB(x, y, convert16_32(color));
index += 2;
}
}
g.drawImage(img, 0, 0, this);
}
public void writeData(int d){//called from a seperate thread
if(writing){
memory[location] = d;
location ++;
if(location == 153600){
location = 0;
for (int n : memory) { //debug check to make sure the memory was properly written to
System.out.println(memory[n]);//prints 255 like it should
}
writing = false;
}
}
}
public void writeCommand(){
writing = true;
}
public Screen() {
img = new BufferedImage(320, 240, BufferedImage.TYPE_USHORT_565_RGB);
timer = new Timer(1000/30, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!writing) { //ensures screen is not updated when writing to memory
action();
}
}
});
timer.start();
}
private void action(){
this.repaint();
}
private int convert16_32(int rgb) { // conerts 16 bit color to 32 bit color
int r = ((rgb & 0xF800) << 16);
int g = ((rgb & 0x07E0) << 11);
int b = ((rgb & 0x001F) << 5);
return (r | g | b);
}
}
我已经尝试将编写代码包含在SwingUtilities.invokeLater()
方法中,但这只会导致严重延迟并且无法解决问题。有人可以帮助我找到我正在做的事情,因为我没有想法。
答案 0 :(得分:0)
问题很可能是您没有正确地同步线程之间的内存访问。因此,DSP线程很可能将其数据写入其处理器高速缓存,但是数据被丢弃而不是被刷新到主存储器以供其他线程查看。
您需要以某种方式同步对memory
数组的访问。最简单的方法是将paintComponent
和writeData
方法都设为synchronized
。根据您的特定应用程序的行为方式,这可能会导致比您希望的更多争用,因此您可能需要使用更复杂的方法,但是当您希望在一个线程中写入的数据可见时,需要一些同步方法其他线程。