简体   繁体   中英

Not getting expected output multi threaded blocking queue

We are trying take data from blocking queue in multi threaded environment.

As we know blocking queue is thread safe and take data from blocking queue in FIFO manner. But not getting expected output.

Please find below program for reference

package com.example.demo;

class PriceTask implements Runnable {
    @Override
    public void run() {
        while (true) {
            try {
                String data = QueueData.bq.take();
                System.out.println(data);
            } catch (Exception ex) {

            }
        }
    }
}

public class SimpleTestDemo {
    public static void main(String[] args) throws Exception {
        QueueData obj1 = new QueueData();
        obj1.m1();
        Thread t1 = new Thread(new PriceTask(), "T1");
        Thread t2 = new Thread(new PriceTask(), "T2");
        t1.start();
        t2.start();
    }
}

package com.example.demo;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class QueueData {

    public static final BlockingQueue<String> bq = new LinkedBlockingQueue<String>();   

    public void m1() throws InterruptedException {
        bq.put("Data--01");
        bq.put("Data--02");
        
        bq.put("Data--03");
        bq.put("Data--04");
        
        bq.put("Data--05");
        bq.put("Data--06");
        
        bq.put("Data--07");
        bq.put("Data--08");
        
        bq.put("Data--09");
        bq.put("Data--10");
    }
}

Getting output as below

Data--01
Data--03
Data--04
Data--05
Data--06
Data--07
Data--08
Data--09
Data--10
Data--02

Expected output

Data--01
Data--02
Data--03
Data--04
Data--05
Data--06
Data--07
Data--08
Data--09
Data--10

While the take method is blocking, the body of the loop in your PriceTask is not atomic. In other words, while data is taken in order, there's no guarantee that after an item is retrieved from the queue there won't be a context switch, and another item may be retrieved and printed before the current item.

One way to gaurantee the items are indeed printed in order is to synchronize the body of the loop. Eg:

class PriceTask implements Runnable {
    @Override
    public void run() {
        while (true) {
            try {
                synchronized (PriceTask.class) {
                    String data = QueueData.bq.take();
                    System.out.println(data);
                }
            } catch (Exception ex) {
        }
    }
}

You are having multi threaded PriceTask to read from same queue but expecting sequential processing of data. This is contradictory. If you want sequential processing then have a single thread PriceTask.

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