java多线程与线程池
1. 场景描述
以前多线程也常用,这次因需再页面上用到多线程,如下图,总结下,有需要的朋友可以参考下。

2. 解决方案
2.1 线程池概念
线程池官方定义不说了,通俗说下:池子的概念,事先(预定义)创建后,后续的线程可以直接从池子中拿,好处:
(1)来创建线程比较消耗资源,不用重复创建;
(2)池子事先定义好,避免无节制创建线程,导致系统出现不可预测风险。
2.2 创建方式
采用jdk自带的线程池创建方式,jdk1.5开始提供,在java.util.concurrent 的包下面。
表面上有两种创建方式,其实一种。
(1)一种是采用new ThreadPoolExecutor进行创建;
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
(2)一种是采用Executors.newFixedThreadPool(3),不过还是调用的new ThreadPoolExecutor进行的线程池创建,赋值了几个默认参数而已。
new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
2.3 参数含义
一共有 7 个参数:
(1)corePoolSize
核心线程数,当有任务进来的时候,如果当前线程数还未达到 corePoolSize 个数,则创建核心线程,核心线程有几个特点:
1、当线程数未达到核心线程最大值的时候,新任务进来,即使有空闲线程,也不会复用,仍然新建核心线程;2、核心线程一般不会被销毁,即使是空闲的状态,但是如果通过方法 allowCoreThreadTimeOut(boolean value) 设置为 true 时,超时也同样会被销毁;3、生产环境首次初始化的时候,可以调用 prestartCoreThread() 方法来预先创建所有核心线程,避免第一次调用缓慢;
(2)maximumPoolSize
除了有核心线程外,有些策略是当核心线程完全无空闲的时候,还会创建一些临时的线程来处理任务,maximumPoolSize 就是核心线程 + 临时线程的最大上限。临时线程有一个超时机制,超过了设置的空闲时间没有事儿干,就会被销毁。
(3)keepAliveTime
这个就是上面两个参数里所提到的超时时间,也就是线程的最大空闲时间,默认用于非核心线程,通过 allowCoreThreadTimeOut(boolean value) 方法设置后,也会用于核心线程。
(4)unit
这个参数配合上面的 keepAliveTime ,指定超时的时间单位,秒、分、时等。
(5)workQueue
等待执行的任务队列,如果核心线程没有空闲的了,新来的任务就会被放到这个等待队列中。
(6)threadFactory
它是一个接口,用于实现生成线程的方式、定义线程名格式、是否后台执行等等,可以用 Executors.defaultThreadFactory() 默认的实现即可,也可以用 Guava 等三方库提供的方法实现,如果有特殊要求的话可以自己定义。它最重要的地方应该就是定义线程名称的格式,便于排查问题了吧。
(7)handler
当没有空闲的线程处理任务,并且等待队列已满(当然这只对有界队列有效),再有新任务进来的话,就要做一些取舍了,而这个参数就是指定取舍策略的,有下面四种策略可以选择:
ThreadPoolExecutor.AbortPolicy:直接抛出异常,这是默认策略;
ThreadPoolExecutor.DiscardPolicy:直接丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后将新来的任务加入等待队列
ThreadPoolExecutor.CallerRunsPolicy:由线程池所在的线程处理该任务,比如在 main 函数中创建线程池,如果执行此策略,将有 main 线程来执行该任务
2.4 测试验证
2.4.1 测试线程
package com.yutong.laowang.test;
public class ThreadTest extends Thread{
@Override
public void run() {
System.out.println("软件老王:" +Thread.currentThread().getName());
}
}
2.4.2 Executors创建
private static void test4() {
Executor mExecutor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
Thread thread = new ThreadTest();
mExecutor.execute(thread);
}
}
结果:
软件老王:pool-2-thread-2
软件老王:pool-2-thread-3
软件老王:pool-2-thread-1
软件老王:pool-2-thread-3
软件老王:pool-2-thread-2
软件老王:pool-2-thread-1
软件老王:pool-2-thread-3
软件老王:pool-2-thread-2
软件老王:pool-2-thread-3
软件老王:pool-2-thread-1
2.4.3 ThreadPoolExecutor创建
private static void test3() {
int poolSize = 5;
int queueSize = 100;
ExecutorService executorService = new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(queueSize), new ThreadPoolExecutor.AbortPolicy());
for (int i=0;i<10;i++) {
executorService.submit(new ThreadTest());
}
}
结果:
软件老王:pool-2-thread-1
软件老王:pool-2-thread-3
软件老王:pool-2-thread-4
软件老王:pool-2-thread-2
软件老王:pool-2-thread-5
软件老王:pool-2-thread-5
软件老王:pool-2-thread-1
软件老王:pool-2-thread-2
软件老王:pool-2-thread-2
软件老王:pool-2-thread-1
2.4.4 线程停用
thread.interrupt();
---有时候不一定能执行成功,一般会结合判断使用,软件老王,例如:
在ThreadTest类中进行判断,默认为false,当满足条件下为true,停用线程。
public volatile boolean exit = false;
I’m 「软件老王」,如果觉得还可以的话,关注下呗,后续更新秒知!欢迎讨论区、同名公众号留言交流!
java多线程与线程池的更多相关文章
- Java多线程与线程池技术
一.序言 Java多线程编程线程池被广泛使用,甚至成为了标配. 线程池本质是池化技术的应用,和连接池类似,创建连接与关闭连接属于耗时操作,创建线程与销毁线程也属于重操作,为了提高效率,先提前创建好一批 ...
- Java 多线程:线程池
Java 多线程:线程池 作者:Grey 原文地址: 博客园:Java 多线程:线程池 CSDN:Java 多线程:线程池 工作原理 线程池内部是通过队列结合线程实现的,当我们利用线程池执行任务时: ...
- java多线程、线程池及Spring配置线程池详解
1.java中为什么要使用多线程使用多线程,可以把一些大任务分解成多个小任务来执行,多个小任务之间互不影像,同时进行,这样,充分利用了cpu资源.2.java中简单的实现多线程的方式 继承Thread ...
- Java多线程和线程池
转自:http://blog.csdn.net/u013142781/article/details/51387749 1.为什么要使用线程池 在Java中,如果每个请求到达就创建一个新线程,开销是相 ...
- Java多线程之线程池详解
前言 在认识线程池之前,我们需要使用线程就去创建一个线程,但是我们会发现有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因 ...
- JAVA多线程(三) 线程池和锁的深度化
github演示代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-servic ...
- Java多线程-ThreadPool线程池(三)
开完一趟车完整的过程是启动.行驶和停车,但老司机都知道,真正费油的不是行驶,而是长时间的怠速.频繁地踩刹车等动作.因为在速度切换的过程中,发送机要多做一些工作,当然就要多费一些油. 而一个Java线程 ...
- java 多线程 4 线程池
系统启动一个新线程的成本是比较高的,因为它涉及到与操作系统的交互.在这种情况下,使用线程池可以很好的提供性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池. 与数据库连接池类似 ...
- Java多线程之线程池
现在是多核的时代,面向多核的编程很重要,因此基于java的并发和多线程开发非常重要. 线程池是于队列密切相关的,其中队列保存了所有等待执行的任务.工作者线程的任务很简单:从队列中获取一个任务,执行任务 ...
- Java多线程(四) 线程池
一个优秀的软件不会随意的创建.销毁线程,因为创建和销毁线程需要耗费大量的CPU时间以及需要和内存做出大量的交互.因此JDK5提出了使用线程池,让程序员把更多的精力放在业务逻辑上面,弱化对线程的开闭管理 ...
随机推荐
- 第一个appium测试用例
from time import sleep from appium import webdriver import pytest class TestXueqiu: user_profile_id ...
- %%%GXZ大佬回关
- 如何在Vue项目中给路由跳转加上进度条
1.前言 在平常浏览网页时,我们会注意到在有的网站中,当点击页面中的链接进行路由跳转时,页面顶部会有一个进度条,用来标示页面跳转的进度(如下图所示).虽然实际用处不大,但是对用户来说,有个进度条会大大 ...
- Xshell6配置ssh免密码登录虚拟机
首先先说明一下有密码的,涉及到root登陆权限的问题: 1.用超级管理员身份登录,修改 vi /etc/ssh/sshd_config, 找到 把其中的permitRootLogin 修改成: # ...
- 46 Linden Street ACT II
46 Linden Street ACT II Excuse me , officer. Can you help me? Sure. Can you tell me, How to get to L ...
- 你知道MySQL中的主从延迟吗?
前言 在一个MySQL主备关系中,每个备库接受主库的binlog并执行. 正常情况下,只要主库执行更新生成所有的binlog,都可以传到备库并被正常的执行,这样备库就能够达到跟主库一样的状态,这就是最 ...
- javascript JSMpeg.js 播放视频解决不用全屏也能播放(也支持自动播放哦)
javascript JSMpeg.js 播放视频解决不用全屏也能播放(也支持自动播放哦) 缺陷就是 因为采用的是 MPEG1解码器 所以清晰度有点低 做直播可以考虑下 如果要清晰度高点 可以采取序列 ...
- cocos creator 3D | 蚂蚁庄园运动会星星球
上一篇文章写了一个简易版的蚂蚁庄园登山赛,有小伙伴留言说想要看星星球的,那么就写起来吧! 效果预览 配置环境 cocos creator 3d 1.0.0 小球点击 3d里节点无法用 cc.Node. ...
- T-SQL Part IX, PIVOT and UNPIVOT
不同于CROSS JOIN, CROSS APPLY, OUTER APPLY,MSDN文档对PIVOT和UNPIVOT 想得重视了一点,单独做了一个页面来介绍. 简单来说,PIVOT用来把行转成列, ...
- C++中对C的扩展学习新增语法——引用
引用 引用的好处: 1.引用的好处 C++使用结构体,不需要再使用 typedef. 2.值传递是将实参进行拷贝,赋值给形参,如果对象比较大,每次拷贝效率比较低,并且函数内部无法修改外部变量的值,能力 ...