【並發】8、借助redis 實現多線程生產消費阻塞隊列


 

 

 

 

顧名思義這個就是再消費的時候,不是之前的那哥用yield進行線程切換的操作,而是用線程等待阻塞的方式去執行,說實話我感覺效率不一定有之前那個好,

因為我對這種阻塞隊列使用的時候,之前有發現阻塞隊列,塞着塞着線程就會進入假死狀態,這個很奇怪,但是有的時候又是好的,這個也不清楚到底是為什么

但是畢竟也是一種實現,我就寫出來了看看吧

生產者

package queue.redisQueue;

import queue.fqueue.vo.TempVo;
import redis.clients.jedis.Jedis;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.UUID;

/**
 * @ProjectName: cutter-point
 * @Package: queue.redisQueue
 * @ClassName: RedisQueueProducter2
 * @Author: xiaof
 * @Description: ${description}
 * @Date: 2019/6/12 16:29
 * @Version: 1.0
 */
public class RedisQueueProducter2 implements Runnable {

    private Jedis jedis;
    private String queueKey;

    public RedisQueueProducter2(Jedis jedis, String queueKey) {
        this.jedis = jedis;
        this.queueKey = queueKey;
    }

    @Override
    public void run() {

        while(true) {

            try {
                Thread.sleep((long) (Math.random() * 1000));

                //不存在則創建,存在則直接插入
                //向redis隊列中存放數據
                //生成數據
                TempVo tempVo = new TempVo();
                tempVo.setName(Thread.currentThread().getName() + ",time is:" + UUID.randomUUID());
                //序列化為字節
                ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(arrayOutputStream);
                objectOutputStream.writeObject(tempVo);
                arrayOutputStream.flush();

                try {
                    int i = 0;
                    while(i < 10) {
                        long num = jedis.lpush(queueKey.getBytes(), arrayOutputStream.toByteArray());
                        if(num > 0) {
                            System.out.println("成功!");
                            break;
                        }

                        ++i;
                    }
                } catch (Exception e) {
                    System.out.println("失敗!");
//                    long num = jedis.lpush(queueKey.getBytes(), arrayOutputStream.toByteArray());
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

 

消費者

package queue.redisQueue;

import queue.fqueue.vo.EventVo;
import redis.clients.jedis.Jedis;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;

/**
 * @ProjectName: cutter-point
 * @Package: queue.redisQueue
 * @ClassName: RedisQueueConsume2
 * @Author: xiaof
 * @Description: ${description}
 * @Date: 2019/6/12 16:40
 * @Version: 1.0
 */
public class RedisQueueConsume2 implements Runnable {

    private Jedis jedis;
    private String queueKey;

    public RedisQueueConsume2(Jedis jedis, String queueKey) {
        this.jedis = jedis;
        this.queueKey = queueKey;
    }


    @Override
    public void run() {


        while(true) {
            List<byte[]> bytesList = null;
            try{
                //這種就是阻塞隊列模式
                bytesList = jedis.blpop(0, queueKey.getBytes());
            } catch (Exception e) {

            }

            //反序列化對象
            if(bytesList == null || bytesList.size() <= 0) {
                Thread.yield();
                continue;
            }

            //獲取第二個對象,就是我們的字節數組
            System.out.println(new String(bytesList.get(0)));
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytesList.get(1));
            try {
                ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
                EventVo eventVo = (EventVo) objectInputStream.readObject();

                eventVo.doOperater();

            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

 

測試代碼

消費隊列

 

 

 接下來我們把生產線程停掉

 

 此時隊列還有

 

 我們把它消費完

 

 

 當只剩最后一個的時候

 

 

 

 可以進入下一步,好當隊列為空的時候,我們再嘗試去取數據的時候

 

 隊列會阻塞再這個地方,相當於是掛起線程

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM