简体   繁体   中英

Regarding ConcurrentLinkedQueue

I have a multi-threaded scenario in which a Sender class which uses a ConcurrentLinkedQueue of type Packet is used. Packet is a POJO defined as:

class Packet {
    int seq;
    byte[] data;
}

Sender class is defined as:

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);
       }
   }
}

From another java class I am reading a file into byte array and adding it to ConcurrentLinkedQueue. When I print the details of packet in enqueue(), I get the correct details. But when I print the details in run() ie after removing the packet from queue, I get the correct seq but I get the data of the last packed that was added to the queue. This happens for all the packets which are removed from the queue.

The data is added by the following method

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

Please suggest. TIA

You are using the same byte array ( fileInBytes ) to read from the stream:

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

I guess that the constructor of Packet does not copy the byte array:

class Packet {
    int seq;
    byte[] data;

    public Packet(int seq, byte[] data) {
       this.seq = seq;
       this.data = data;
   }
}

That means that all of your Packet.data fields point to the same byte array which is overwritten each time your read from the stream.

You need to use a copy:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM