ThreadPoolExecutor线程池 + Queue队列

1:BlockingQueue继承关系

  java.util.concurrent 包里的 BlockingQueue是一个接口, 继承Queue接口,Queue接口继承 Collection

 

  BlockingQueue----->Queue-->Collection

 图:

 

队列的特点是:先进先出(FIFO)

 

2:BlockingQueue的方法

BlockingQueue 具有 4 组不同的方法用于插入、移除以及对队列中的元素进行检查。如果请求的操作不能得到立即执行的话,每个方法的表现也不同。这些方法如下:

 

 

 抛出异常特殊值阻塞超时
插入add(e)offer(e)put(e)offer(e, time, unit)
移除remove()poll()take()poll(time, unit)
检查element()peek()不可用不可用
 

 

 

四组不同的行为方式解释:

1(异常)

如果试图的操作无法立即执行,抛一个异常。

2(特定值) 

如果试图的操作无法立即执行,返回一个特定的值(常常是 true / false)。

3(阻塞) 

如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行。

4(超时) 

如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行,但等待时间不会超过给定值。返回一个特定值以告知该操作是否成功(典型的是 true / false)。

  

1.首先是springBoot的项目框架如下:

2.业务测试流程涉及的类,如下

BusinessThread 类


package com.springboot.demo.Threads;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;


/**
 * Created by Administrator on 2018/5/9.
 */
@Component
@Scope("prototype")//spring 多例
public class BusinessThread implements Runnable{

    private String acceptStr;

    public BusinessThread(String acceptStr) {
        this.acceptStr = acceptStr;
    }

    public String getAcceptStr() {
        return acceptStr;
    }

    public void setAcceptStr(String acceptStr) {
        this.acceptStr = acceptStr;
    }

    @Override
    public void run() {
        //业务操作
        System.out.println("多线程已经处理订单插入系统,订单号:"+acceptStr);

        //线程阻塞
        /*try {
            Thread.sleep(1000);
            System.out.println("多线程已经处理订单插入系统,订单号:"+acceptStr);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
    }
}

TestThreadPoolManager 类


package com.springboot.demo.Threads;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Queue;
import java.util.concurrent.*;

/**
 * Created by Administrator on 2018/5/10.
 */
@Component
public class TestThreadPoolManager implements BeanFactoryAware {

    //用于从IOC里取对象
    private BeanFactory factory; //如果实现Runnable的类是通过spring的application.xml文件进行注入,可通过 factory.getBean()获取,这里只是提一下

    // 线程池维护线程的最少数量
    private final static int CORE_POOL_SIZE = 2;
    // 线程池维护线程的最大数量
    private final static int MAX_POOL_SIZE = 10;
    // 线程池维护线程所允许的空闲时间
    private final static int KEEP_ALIVE_TIME = 0;
    // 线程池所使用的缓冲队列大小
    private final static int WORK_QUEUE_SIZE = 50;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        factory = beanFactory;
    }

    /**
     * 用于储存在队列中的订单,防止重复提交,在真实场景中,可用redis代替 验证重复
     */
    Map<String, Object> cacheMap = new ConcurrentHashMap<>();


    /**
     * 订单的缓冲队列,当线程池满了,则将订单存入到此缓冲队列
     */
    Queue<Object> msgQueue = new LinkedBlockingQueue<Object>();


    /**
     * 当线程池的容量满了,执行下面代码,将订单存入到缓冲队列
     */
    final RejectedExecutionHandler handler = new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            //订单加入到缓冲队列
            msgQueue.offer(((BusinessThread) r).getAcceptStr());
            System.out.println("系统任务太忙了,把此订单交给(调度线程池)逐一处理,订单号:" + ((BusinessThread) r).getAcceptStr());
        }
    };


    /**创建线程池*/
   final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue(WORK_QUEUE_SIZE), this.handler);


    /**将任务加入订单线程池*/
    public void addOrders(String orderId){
        System.out.println("此订单准备添加到线程池,订单号:" + orderId);
        //验证当前进入的订单是否已经存在
        if (cacheMap.get(orderId) == null) {
            cacheMap.put(orderId, new Object());
            BusinessThread businessThread = new BusinessThread(orderId);
            threadPool.execute(businessThread);
        }
    }

    /**
     * 线程池的定时任务----> 称为(调度线程池)。此线程池支持 定时以及周期性执行任务的需求。
     */
    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);


    /**
     * 检查(调度线程池),每秒执行一次,查看订单的缓冲队列是否有 订单记录,则重新加入到线程池
     */
    final ScheduledFuture scheduledFuture = scheduler.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            //判断缓冲队列是否存在记录
            if(!msgQueue.isEmpty()){
                //当线程池的队列容量少于WORK_QUEUE_SIZE,则开始把缓冲队列的订单 加入到 线程池
                if (threadPool.getQueue().size() < WORK_QUEUE_SIZE) {
                    String orderId = (String) msgQueue.poll();
                    BusinessThread businessThread = new BusinessThread(orderId);
                    threadPool.execute(businessThread);
                    System.out.println("(调度线程池)缓冲队列出现订单业务,重新添加到线程池,订单号:"+orderId);
                }
            }
        }
    }, 0, 1, TimeUnit.SECONDS);


    /**获取消息缓冲队列*/
    public Queue<Object> getMsgQueue() {
        return msgQueue;
    }

    /**终止订单线程池+调度线程池*/
    public void shutdown() {
        //true表示如果定时任务在执行,立即中止,false则等待任务结束后再停止
        System.out.println("终止订单线程池+调度线程池:"+scheduledFuture.cancel(false));
        scheduler.shutdown();
        threadPool.shutdown();

    }
}
TestController 类


package com.springboot.demo;

import com.springboot.demo.Threads.TestThreadPoolManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Queue;
import java.util.UUID;

/**
 * Created by Administrator on 2018/5/9.
 */
@RestController
public class TestController {

    @Autowired
    TestThreadPoolManager testThreadPoolManager;

    /**
     * 测试模拟下单请求 入口
     * @param id
     * @return
     */
    @GetMapping("/start/{id}")
    public String start(@PathVariable Long id) {
        //模拟的随机数
        String orderNo = System.currentTimeMillis() + UUID.randomUUID().toString();

        testThreadPoolManager.addOrders(orderNo);

        return "Test ThreadPoolExecutor start";
    }

    /**
     * 停止服务
     * @param id
     * @return
     */
    @GetMapping("/end/{id}")
    public String end(@PathVariable Long id) {

        testThreadPoolManager.shutdown();

        Queue q = testThreadPoolManager.getMsgQueue();
        System.out.println("关闭了线程服务,还有未处理的信息条数:" + q.size());
        return "Test ThreadPoolExecutor start";
    }
}

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/386776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux基础文件管理软硬链接

一、文件系统的基本结构 1、文件和目录被组成一个单根倒置树目录结构 2、文件系统从根目录下开始&#xff0c;用“/”表示 3、根文件系统&#xff08;rootfs&#xff09;&#xff1a;root filesystem文件名区分大小写 4、以 . 开头的文件为隐藏文件 5、路径用/隔离 6文件有两类…

mybatis动态更新xml文件后热部署,不重启应用的方法

mybatis应用程序&#xff0c;由于是半自动化的sql, 有大量的sql是在xml文件中配置的&#xff0c;而在开发程序的过程中&#xff0c;通常需要边写sql变调试应用。但在默认情况下&#xff0c;xml文件里配置的sql语句是被放入到缓存中去了&#xff0c;每次更改有sql语句的xml文件&…

下拉插件 (带搜索) Bootstrap-select 从后台获取数据填充到select的 option中 用法详解...

今天收到了客户的需求&#xff0c;要求在新增停车场ID的时候要从数据库查出来对应的停车场名称然后显示在界面上。保存的时候按照停车场ID进行保存。 自己首先把后台的部分写完了&#xff0c;测试了接口数据。成功的拿到了ajax数据。 接下来&#xff0c;自己用了select下拉标签…

Linux自有服务(2)-Linux从入门到精通第六天(非原创)

文章大纲 一、设置主机名二、chkconfig三、ntp服务四、防火墙服务五、rpm管理&#xff08;重点&#xff09;六、cron/crontab计划任务&#xff08;重点&#xff09;七、学习资料下载八、参考文章 自有服务&#xff0c;即不需要用户独立去安装的软件的服务&#xff0c;而是当系统…

营销-营销方式:营销方式

ylbtech-营销-营销方式&#xff1a;营销方式营销方式是指营销过程中所有可以使用的方法。包括服务营销、体验营销、知识营销、情感营销、教育营销、差异化营销、直销、网络营销等。要有好的营销方式首先要创造行之有效的营销工具。但这并不意味着要把预算的75%都花在印制宣传资…

Kibana可视化管理页面详细使用说明

Kibana可视化管理页面详细使用说明 使用浏览器访问 ip:5601 默认端口&#xff0c;进入首页 Discover&#xff1a;日志管理视图 主要进行搜索和查询 Visualize&#xff1a;统计视图 构建可视化的图表 Dashboard&#xff1a;仪表视图 将构…

OO_BLOG3_规格化设计(JML学习)

目录 JML语言学习笔记理论基础应用工具链情况JMLUnit/JMLUnitNGUNIT3 作业分析作业 3-1 实现两个容器类Path和PathContainer作业 3-2 实现容器类Path和数据结构类Graph作业 3-3 实现容器类Path&#xff0c;地铁系统类RailwaySystem规格撰写的心得与体会最后&#xff0c;衷心感谢…

CMU Database Systems - Sorting,Aggregation,Join

Sorting 排序如果可在内存里面排&#xff0c;用经典的排序算法就ok&#xff0c;比如快排 问题在于&#xff0c;数据表中的的数据是很多的&#xff0c;没法一下都放到内存里面进行排序 所以就需要用到&#xff0c;外排&#xff0c;多路并归排序 看下最简单的&#xff0c;2路并归…

springboot线程池的使用和扩展

实战环境 windowns10&#xff1b;jdk1.8&#xff1b;springboot 1.5.9.RELEASE&#xff1b;开发工具&#xff1a;IntelliJ IDEA&#xff1b; 实战源码 本次实战的源码可以在我的GitHub下载&#xff0c;地址&#xff1a;gitgithub.com:zq2599/blog_demos.git&#xff0c;项目主…

通过Rancher安装K8s

说明 我们用kubernetes去管理Docker集群&#xff0c;即可以将Docker看成Kubernetes内部使用的低级别组件。另外&#xff0c;kubernetes不仅仅支持Docker&#xff0c;还支持Rocket&#xff0c;这是另一种容器技术。希望我这篇文章中简单的描述能让你对两者有所理解和认识。 机…

35. 搜索插入位置-LeetCode

心得&#xff1a;这个题也是二分查找&#xff0c;但是有个小技巧&#xff1a;当left>right的时候 left就是要插入的位置。 代码&#xff1a; 1 class Solution {2 public int searchInsert(int[] nums, int target) {3 if(numsnull||nums.length0)4 …

Kubectl指令集

1 Kubectl指令集 1.1 Master查询节点信息 [rootmaster1 kubernetes-1.10]# kubectl get nodes 1.2 查询所有Pod信息 [rootmaster1 ~]# kubectl get pods --namespacekube-system 1.3 查询故障的Pod信息 [rootmaster1 ~]# kubectl get pods -n kube-sys…

实验五报告

一、实验结论&#xff1a; 1. 二分查找&#xff1a;补足程序ex1_1.cpp// 练习&#xff1a;使用二分查找&#xff0c;在一组有序元素中查找数据项 // 形参是数组&#xff0c;实参是数组名 #include <stdio.h> const int N5; int binarySearch(int x[], int n, int item…

实验五 网络编程与安全-----实验报告

一、实验五 网络编程与安全-1 1.实验要求&#xff1a; 两人一组结对编程&#xff1a; &#xff08;1&#xff09;参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA &#xff1b; &#xff08;2&#xff09;结对实现中缀表达式转后缀表达式的功能 MyBC.java&#xff1b…

Docker版本Jenkins的使用

Docker版本Jenkins的使用 低调的微胖关注赞赏支持 Docker版本Jenkins的使用 12018.05.15 18:21:50字数 1202阅读 22588 一. 什么是Jenkins Jenkins是当前非常流行的一款持续集成工具&#xff0c;可以帮助大家把更新后的代码自动部署到服务器上运行。 二. 为什么用docker版…

小程序 setData 中的坑,其实好像...

最近这段时间在写微信小程序&#xff0c;有一个页面需要动态修改 data 中的数据&#xff0c;而这里似乎是个坑。 1、正常修改 正常修改很简单&#xff0c;当触发 change 事件时&#xff0c;数据和页面都会同时发生改变。这个也不用多说&#xff0c;很简单的例子。 2、如何修改对…

CentOS HarBor安装与配置

HarBor 安装与配置 Prerequisites for the target host ResourceCapacityDescriptionCPUminimal 2 CPU4 CPU is preferredMemminimal 4GB8GB is preferredDiskminimal 40GB160GB is preferred 环境 centos7harbor v1.6.3python v2.7及以上docker v1.10及以上docker-compose …

phpstudy如何安装景安ssl证书 window下apache服务器网站https访问

1. 下载景安免费证书 https://www.zzidc.com/help/helpDetail?id555 2.文件解压上传至服务器&#xff0c;位置自己决定 3. 调整apache配置 景安原文链接&#xff1a;https://www.zzidc.com/help/helpDetail?id555 ① 确保你的apache编译了ssl模块&#xff0c;这是支持ssl证书…

docker下gitlab安装配置使用(完整版)

docker下gitlab安装配置使用(完整版) 22018.12.16 00:07:57字数 737阅读 17595 docker 安装gitlab以及使用 一、安装及配置 1.gitlab镜像拉取 # gitlab-ce为稳定版本&#xff0c;后面不填写版本则默认pull最新latest版本 $ docker pull gitlab/gitlab-ce拉取镜像 2.运行g…

企业级应用,如何实现服务化一(项目架构演化)

1.企业级应用架构演化 1.1.架构演化图 1.2.文字描述 #单一应用架构当网站流量很小时&#xff0c;只需一个应用&#xff0c;将所有功能都部署在一起&#xff0c;以减少部署节点和成本#垂直应用架构当访问量逐渐增大&#xff0c;单一应用增加机器带来的加速度越来越小&#xff0c…