我有一个多线程场景,其中使用了使用Packet类型的ConcurrentLinkedQueue的Sender类。数据包是POJO,定义为:
class Packet {
int seq;
byte[] data;
}
发件人类定义为:
class Sender implements Runnable {
private static ConcurrentLinkedQueue<Packet> queue;
public Sender() {
if (ccl == null)
ccl = new ConcurrentLinkedQueue<Packet>();
}
public static boolean enqueue(Packet p) {
if (queue == null) {
queue = new ConcurrentLinkedQueue<Packet>();
}
//System.out.println(p.toString());
return queue.add(p);
}
@Override
public void run() {
TcpSend tcp = new TcpSend();
while (true) {
Packet p = queue.remove();
// some code here
//System.out.println(p.toString());
tcp.send(p);
}
}
}
从另一个java类我正在将文件读入字节数组并将其添加到ConcurrentLinkedQueue。当我在enqueue()中打印数据包的细节时,我得到了正确的细节。但是当我在run()中打印细节时,即从队列中删除数据包之后,我得到了正确的seq,但是我得到了添加到队列中的最后一个打包的数据。对于从队列中删除的所有数据包都会发生这种情况。
通过以下方法添加数据
public void addPacket() {
int bytesRead = 0;
int seq = 1;
byte[] fileInBytes = new byte[1500];
BufferedInputStream in = new BufferedInputStream(new
FileInputStream(fileName));
while((bytesRead = in.read(fileInBytes)) != -1) {
Sender.enqueue(new Packet(seq, fileInBytes);
seq++;
}
}
请建议。 TIA
答案 0 :(得分:1)
您正在使用相同的字节数组(fileInBytes
)从流中读取:
byte[] fileInBytes = new byte[1500];
BufferedInputStream in = new BufferedInputStream(new
FileInputStream(fileName));
while((bytesRead = in.read(fileInBytes)) != -1) {
Sender.enqueue(new Packet(seq, fileInBytes);
seq++;
}
我猜Packet的构造函数不会复制字节数组:
class Packet {
int seq;
byte[] data;
public Packet(int seq, byte[] data) {
this.seq = seq;
this.data = data;
}
}
这意味着所有Packet.data字段都指向同一个字节数组,每次从流中读取时都会被覆盖。
您需要使用副本:
byte[] fileInBytes = new byte[1500];
BufferedInputStream in = new BufferedInputStream(new
FileInputStream(fileName));
while((bytesRead = in.read(fileInBytes)) != -1) {
byte[] packetBytes = Arrays.copyOf(fileInBytes, bytesRead);
Sender.enqueue(new Packet(seq, packetBytes );
seq++;
}