关于ConcurrentLinkedQueue

时间:2015-03-04 07:43:34

标签: java multithreading concurrency queue

我有一个多线程场景,其中使用了使用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

1 个答案:

答案 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++;
}