Java多线程和线程池
来源:互联网 发布:富途证券招聘网络销售 编辑:程序博客网 时间:2024/06/05 15:12
1.为什么要使用线程池
在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,服务器应用程序需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利 用已有对象来进行服务,这就是“池化资源”技术产生的原因。
线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。
2.线程池的组成部分
一个比较简单的线程池至少应包含线程池管理器、工作线程、任务列队、任务接口等部分。其中线程池管理器的作用是创建、销毁并管理线程池,将工作线程放入线程池中;工作线程是一个可以循环执行任务的线程,在没有任务是进行等待;任务列队的作用是提供一种缓冲机制,将没有处理的任务放在任务列队中;任务接口是每个任务必须实现的接口,主要用来规定任务的入口、任务执行完后的收尾工作、任务的执行状态等,工作线程通过该接口调度任务的执行。
线程池管理器至少有下列功能:创建线程池,销毁线程池,添加新任务。
工作线程是一个可以循环执行任务的线程,在没有任务时将等待。
任务接口是为所有任务提供统一的接口,以便工作线程处理。任务接口主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等。
3.线程池适合应用的场合
当一个服务器接受到大量短小线程的请求时,使用线程池技术是非常合适的,它可以大大减少线程的创建和销毁次数,提高服务器的工作效率。
Java自带线程池
先看看Java自带线程池的例子,开启5个线程打印字符串List:
import java.util.ArrayList;import java.util.List;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ThreadTest { public static void main(String[] args) { List<String> strList = new ArrayList<String>(); for (int i = 0; i < 100; i++) { strList.add("String" + i); } int threadNum = strList.size() < 5 ? strList.size() : 5; ThreadPoolExecutor executor = new ThreadPoolExecutor(2, threadNum, 300, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(3), new ThreadPoolExecutor.CallerRunsPolicy()); for (int i = 0; i < threadNum; i++) { executor.execute(new PrintStringThread(i,strList,threadNum)); } executor.shutdown(); }}class PrintStringThread implements Runnable { private int num; private List<String> strList; private int threadNum; public PrintStringThread(int num, List<String> strList, int threadNum) { this.num = num; this.strList = strList; this.threadNum = threadNum; } public void run() { int length = 0; for(String str : strList){ if (length % threadNum == num) { System.out.println("线程编号:" + num + ",字符串:" + str); } length ++; } }}Java自带线程池构造方法
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueueRejectedExecutionHandler handler)corePoolSize: 线程池维护线程的最少线程数,也是核心线程数,包括空闲线程
maximumPoolSize: 线程池维护线程的最大线程数
keepAliveTime: 线程池维护线程所允许的空闲时间
unit: 程池维护线程所允许的空闲时间的单位
workQueue: 线程池所使用的缓冲队列
handler: 线程池对拒绝任务的处理策略
当一个任务通过execute(Runnable)方法欲添加到线程池时:
1、 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
2、 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
3、如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
4、 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
5、 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
- java多线程和线程池
- Java多线程和线程池
- java 多线程和线程池
- Java多线程和线程池
- java多线程和线程池
- Java多线程和线程池
- Java多线程和线程池
- Java多线程和线程池
- Java 多线程线程池 - Callable和Future
- Java多线程 锁对象和线程池
- Java多线程和线程池(转)
- [java多线程]进程和线程
- java中的线程和多线程
- Java多线程-线程池
- java 多线程- 线程池
- java 多线程线程池
- java多线程:线程池
- java多线程,线程池
- 简单排序算法
- 20种常用DOS命令
- tensorflow中bin数据读取之深入理解(6)---《深度学习》
- Android依赖冲突遇到的坑
- 字节对齐的规则总结
- Java多线程和线程池
- Mongodb启动命令mongod参数说明
- 免费jdk1.8源码下载
- 思科华为华三锐捷交换机端口镜像配置参考
- python对MySQL数据库的操作表单的创建,数据的插入,读取,更新,删除操作
- 贝叶斯算法笔记
- 常见Android Native崩溃及错误原因
- 服网LNMP集群-1.0.5
- socket编程