ArrayBlockingQueue 实现定时推送数据

 

有界阻塞队列,内部使用数组存储元素,有2个常用构造方法:
capacity表示容量大小,默认内部采用非公平锁
public ArrayBlockingQueue(int capacity)
capacity:容量大小,fair:内部是否是使用公平锁
public ArrayBlockingQueue(int capacity, boolean fair)

 

1.demo

public class Demo {
    //推送队列
    static ArrayBlockingQueue<String> pushQueue = new ArrayBlockingQueue<String>(10000);

    static {
        //启动一个线程做真实推送
        new Thread(() -> {
            while (true) {
                String msg;
                try {
                    long starTime = System.currentTimeMillis();
                    //获取一条推送消息,此方法会进行阻塞,直到返回结果
                    msg = pushQueue.take();
                    long endTime = System.currentTimeMillis();
                    //模拟推送耗时
                    TimeUnit.MILLISECONDS.sleep(500);

                    System.out.println(String.format("[%s,%s,take耗时:%s],%s,发送消息:%s", starTime, endTime, (endTime - starTime), Thread.currentThread().getName(), msg));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    //推送消息,需要发送推送消息的调用该方法,会将推送信息先加入推送队列
    public static void pushMsg(String msg) throws InterruptedException {
        pushQueue.put(msg);
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 1; i <= 5; i++) {
            String msg = "消息内容";
            //模拟耗时
            TimeUnit.SECONDS.sleep(i);
            Demo1.pushMsg(msg);
        }
    }
}

创建ArrayBlockingQueue时候需要制定容量大小,调用pushQueue.put将推送信息放入队列中,如果队列已
满,此方法会阻塞。代码中在静态块中启动了一个线程,调用pushQueue.take();从队列中获取待推送的信息进行推送处理。
注意:ArrayBlockingQueue如果队列容量设置的太小,消费者发送的太快,消费者消费的太慢的情况下,会导致队列空间满,
调用put方法会导致发送者线程阻塞,所以注意设置合理的大小,协调好消费者的速度。

 

 

2.

package com...BlockingQueue;

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import wfc.service.database.RecordSet;
import wfc.service.database.SQL;
import java.util.concurrent.*;


@Component
@EnableScheduling//可以在启动类上注解也可以在当前文件
public class BlockingQueues {

    private static ExecutorService service = Executors.newFixedThreadPool(10);
    private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);
//    private static RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();拒绝策略
//    private static ExecutorService executorService = new ThreadPoolExecutor(2, 5, 1, TimeUnit.SECONDS, queue, handler);

    @Scheduled(cron = "0 0/1 * * * ?")//1分钟
    public void query(){
        doSting();
    }

    private static void doSting(){

        new Thread(new Runnable() {
            boolean flag = true;
            @Override
            public void run() {

                System.out.println("开始扫描未推送的办件到BlockingQueue....");
                String type = "0";
                String insertSql = "select * from DANGAN_FJ where TYPE = ? ";
                Object[] insertObject = new Object[] {type};
                RecordSet rs = SQL.execute(insertSql,insertObject);
                while (rs.next()){
                    String ST_FJ_ID = rs.getString("ST_FJ_ID");
                    try {
                        queue.put(ST_FJ_ID);
                    } catch (InterruptedException e) {
                        System.out.println("放入队列出异常...:"+e);
                        e.printStackTrace();
                    }
                }
                System.out.println("BlockingQueue队列里的办件--->:"+queue);

                while (flag) {
                    service.execute(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                String ST_FJ_ID = queue.take();
                                String updateSql = "update dangan_fj set type =-1 where st_fj_id = ? ";
                                Object[] updateObject = new Object[]{ST_FJ_ID};
                                RecordSet updateRs = SQL.execute(updateSql, updateObject);
                                int number = updateRs.TOTAL_RECORD_COUNT;
                                //影响行数
                                System.out.println("办件过期更改影响行数:  " + number + "   办件编号为:" + ST_FJ_ID+"  处理线程:"+Thread.currentThread().getName());

                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                    if(queue.isEmpty()){
                        flag =false;
                    }
                }
            }
        },"").start();

    }


}

 

posted @ 2020-09-30 11:28  Li&Fan  阅读(297)  评论(0编辑  收藏  举报