Java线程池实现原理之自定义线程池(一)
1.队列的概念
谈到多线程先讲下队列的概念,之后的多线程学习会用到此类知识。
队列分为:阻塞式队列(有界)、非阻塞式队列(无界),遵循着先进先出、后进后出的原则。
阻塞队列与非阻塞队列区别:
1.非阻塞式队列超出队列总数会丢失。
2.阻塞式队列超出总数会进入等待(等待时间=设置超时时间)。
3.获取队列方面:非阻塞式队列,如果为空返回null。阻塞式队列,如果为空也会进入等待。
非阻塞式队列ConcurrentLinkedDeque
//非阻塞式队列 无界(可以声明无限个队列)
public static void test1(){ ConcurrentLinkedDeque<Object> objects = new ConcurrentLinkedDeque<>();
objects.offer("java001");
objects.offer("java002"); System.out.println("队列总数:"+objects.size()); //建议:获取队列之后删除
System.out.println("获取队列但不删除:"+objects.peek());
System.out.println("获取队列但不删除,队列总数:"+objects.size());
System.out.println("获取队列删除:"+objects.poll()); //非阻塞式队列,如果为空返回null
System.out.println(objects.poll());
System.out.println(objects.poll());
System.out.println(objects.poll());
System.out.println("获取队列删除,队列总数:"+objects.size());
}
阻塞式队列ArrayBlockingQueue
//阻塞式队列
public static void test2() throws InterruptedException { long startTime=System.currentTimeMillis();
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
arrayBlockingQueue.offer("A001",3, TimeUnit.SECONDS);
arrayBlockingQueue.offer("A002",3, TimeUnit.SECONDS); //阻塞式队列超出总数等待(等待时间=设置超时时间)
arrayBlockingQueue.offer("A003",3, TimeUnit.SECONDS);
arrayBlockingQueue.offer("A004",1, TimeUnit.SECONDS);
arrayBlockingQueue.offer("A005",1, TimeUnit.SECONDS); System.out.println("队列总数:"+arrayBlockingQueue.size());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
//阻塞式队列,如果为空也会等待。
System.out.println(arrayBlockingQueue.poll(1, TimeUnit.SECONDS));
System.out.println("队列剩余总数:"+arrayBlockingQueue.size()); System.out.println("耗时:"+ (System.currentTimeMillis() - startTime)/1000 +"秒"); }
2.线程池
线程池好处:
1.降低资源 => 重复利用机制 (降低创建线程和销毁线程)
2.提高响应效率 => 当任务到达时,任务可以不需要等待去创建线程就可以执行
3.方便管理 => 无限创建线程消耗资源、降低系统稳定性。使用线程池可以统一分配、调优、监控。
线程与任务的区别:
可以把线程理解成一个工作人员。而任务就是这个工作人员干的活。比如,餐厅的工作人员在为顾客传菜,传菜就是个任务。 Java中线程就是Thread类或其子类的一个实例。
也就是说你不必关注线程对象是用哪种方法创建的。在此基础上,线程所执行的代码,即run方法中的代码所实现的处理逻辑,
比如读取数据库中的一条记录,就是一个任务。因此,所谓任务是一个相对的概念。一个任务可以是读取数据库中的一条记录,
也可以是FTP传输一批文件,FTP传输一个文件……
//创建线程四种方式:
//1.可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
//2.定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
//3.可定时线程池,支持定时及周期性任务执行。
//4.单例线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
public static void test1() { //1.可缓存、定时、定长、单例
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i <10 ; i++) {
final int i1 = i;
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+",i:"+ i1);
}
});
} } public static void test2() { //2.可定长线程,核心线程5个,最多创建5个线程 (只会创建5个线程,其他线程共享这5个线程)
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i <10 ; i++) {
final int i1 = i;
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+",i:"+ i1);
}
});
}
} public static void test3() { long l = System.currentTimeMillis();
//3.可定时线程 =>核心线程数3 (延迟三秒执行)
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
for (int i = 0; i <10 ; i++) { final int i1 = i;
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+",i:"+ i1);
System.out.println("耗时:"+ (System.currentTimeMillis() -l)/1000 +"秒" );
}
},3, TimeUnit.SECONDS);
} } public static void test4() { //4.单例线程 =>核心线程数1 最大线程数1
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i <10 ; i++) {
final int i1 = i;
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+",i:"+ i1);
}
});
}
}
Java线程池实现原理之自定义线程池(一)的更多相关文章
- 线程池的原理以及实现线程池的类ExecutorService中方法的使用
1.线程池:线程池就是就像一个容器,而这个容器就是用来存放线程的,且有固定的容量. 如果没有线程池,当需要一个线程来执行任务时就需要创建一个线程,我们设创建线程的时间为t1,执行线程的时间为t2,销毁 ...
- JDBC连接池原理、自定义连接池代码实现
首先自己实现一个简单的连接池: 数据准备: CREATE DATABASE mybase; USE mybase; CREATE TABLE users( uid INT PRIMARY KEY AU ...
- 【Java EE 学习 15】【自定义数据库连接池之动态代理的使用】
一.动态代理的作用 使用动态代理可以拦截一个对象某个方法的执行,并执行自定义的方法,其本质是反射 优点:灵活 缺点:由于其本质是反射,所以执行速度相对要慢一些 二.数据库连接池设计思想 1.为什么要使 ...
- Java 多线程 自定义线程辅助
之前的文章我介绍了C#版本的多线程和自定义线程处理器. 接下来我们来看看Java版本的呢 java 的线程和C#的线程有点区别,java的线程没有是否是后台线程一说,具体原因是java的线程是jvm的 ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
- Executors提供的四种线程池和自定义线程池
JAVA并发编程——EXECUTORS 线程池的思想是一种对象池的思想,开放一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完毕,对象 ...
- 一个自定义线程池的小Demo
在项目中如果是web请求时候,IIS会自动分配一个线程来进行处理,如果很多个应用程序共享公用一个IIS的时候,线程分配可能会出现一个问题(当然也是我的需求造成的) 之前在做项目的时候,有一个需求,就是 ...
- 自定义线程池的名称(ThreadPoolExecutor)
目的:有时候为了快速定位出现错误的位置,在采用线程池时我们需要自定义线程池的名称. 1.创建ThreadFactory(ThreadPoolExecutor默认采用的是DefaultThreadFac ...
- c# 多线程系列二 自定义线程执行器
看了第一篇文章,多线程系列,看到了在线程执行任务队列有了一定的了解~! 那么今天我来讲讲,怎么样构建通用的自定义线程概念! 线程执行任务,肯定要有目标,但是如果写死了,那么一个线程处理执行职能按照思路 ...
随机推荐
- SQL---mysql新增字段
) DEFAULT NULL COMMENT '姓名' 修改表 people 增加字段 name 长度100 默认为null 备注:姓名
- building tool的简单了解
java常用的三种构建工具: Apache Maven ——主要用于构建Java项目的自动化工具. NetBeans IDE 支持 Maven 构建系统,可帮助您管理项目的依赖关系.构建.报告和文档. ...
- Numpy系列(十)- 掩码数组
简介 有时候数据集中存在缺失.异常或者无效的数值,我们可以标记该元素为被屏蔽(无效)状态. import numpy as np import numpy.ma as ma x = np.array( ...
- jQuery使用(十三):工具方法
proxy() onConflict() each() map() parseJson() makeArray() proxy() $.proxy()的实现机制与原生javaScript中的bind( ...
- NOI-OJ 1.13 ID:5 素数回文数的个数
整体思路 使用埃拉拖色尼算法提前计算出1000以内的素数表. 设计一个回文判断函数isHW(int n),难点在于数字回文的判断.一个简单的方法是将数字n使用sprintf输出在一个数组中,然后从数组 ...
- Flask Web中文教程
Flask Web中文教程:http://docs.jinkan.org/docs/flask/
- 网站设置ico图标
1.用设计的png图片去在线图标网站上生成一个16*16大小的图标,命名favcon.ico放置到网站根目录下如:http://www.faviconico.org/favicon2.添加代码 < ...
- [物理学与PDEs]第3章第2节 磁流体力学方程组 2.1 考虑到导电媒质 (等离子体) 的运动对 Maxwell 方程组的修正
1. Maxwell 方程组 $$\bee\label{3_2_1_Maxwell} \bea \Div{\bf D}&=\rho_f,\\ \rot{\bf E}&=-\cfrac ...
- Django之form表单
https://www.cnblogs.com/liwenzhou/p/8747872.html 1. form组件的介绍 之前web开发的模式,以注册为例: 1. 要有一个注册的页面,页面里面要有f ...
- lucene学习的小结
pom.xml设置 <dependency> <groupId>junit</groupId> <artifactId>junit</artifa ...