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# 多线程系列二 自定义线程执行器
看了第一篇文章,多线程系列,看到了在线程执行任务队列有了一定的了解~! 那么今天我来讲讲,怎么样构建通用的自定义线程概念! 线程执行任务,肯定要有目标,但是如果写死了,那么一个线程处理执行职能按照思路 ...
随机推荐
- min_25筛
min_25筛 用来干啥? 考虑一个积性函数\(F(x)\),用来快速计算前缀和\[\sum_{i=1}^nF(i)\] 当然,这个积性函数要满足\(F(x),x\in Prime\)可以用多项式表示 ...
- [PA2014]Druzyny
题目描述 体育课上,n个小朋友排成一行(从1到n编号),老师想把他们分成若干组,每一组都包含编号连续的一段小朋友,每个小朋友属于且仅属于一个组.第i个小朋友希望它所在的组的人数不多于d[i],不少于c ...
- 使用item来封装数据:
一.item和field类: 1.使用Item类: 创建了类Bookitem,然后就可以使用: 2.item_pipeline: 我们可以使用item_pipeline对爬取的数据进行处理. 步骤: ...
- tomcat8 源码分析 | 组件及启动过程
tomcat 8 源码分析 ,本文主要讲解tomcat拥有哪些组件,容器,又是如何启动的 推荐访问我的个人网站,排版更好看呦: https://chenmingyu.top/tomcat-source ...
- pip install升级包
只需要python -m pip install --user --upgrade pip==9.0.3 只需要加一个--user
- C++回顾day02---<运算符重载>
一:运算符重载的限制 (一)可以重载的运算符: + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << > ...
- luoguo 1306 斐波那契公约数
这题难度不大,主要是小结论:斐波那契第n项和第m项公约数就是第gcd(n,m)项 大概能猜出来,毕竟斐波那契数列反过来实在太像计算公约数的步骤了 日后填坑证明吧
- Nginx 站点设置目录列表显示
Nginx 站点目录列表显示. 可以编辑添加在 server { } 模块 或者 location { } 模块下. autoindex on; # 开启目录文件列表 autoindex_exact_ ...
- Wndows下Apache+php+Mysql环境的搭建及其涉及的知识(转)
一.安装Apache 1. 在网上搜索以下3个文件,以及找一个地方新建一个文件夹 好吧,这里有下载链接:http://pan.baidu.com/s/1hr9IdSS 文件夹内有:apache,mys ...
- WEB 3D SVG CAD 向量 几个实施(转)
一.他们所有的发展.从地上爬起来 VML+SVG发展矢量地图.你并不需要导入第三方的图片作为背景,直接在地图编辑器可以在底图内容编辑,由于岩石.巷道.煤层.画水.础地图样子再在其上面画出智慧线等设 ...