JUC之手写一个简单的线程池
[TOC]
JUC之手写一个简单的线程池 在之前介绍了线程池的快捷创建方式以及其中的隐患,紧接着介绍了线程池的标准创建方式,了解了线程池的基本构造后,我们可以自己尝试手写一个简单的线程池来加深我们对线程池的理解。
阻塞队列 首先我们需要一个阻塞队列,用来存放任务,可以向其中添加任务,获取其中的任务,还要实现当队列为空时,不能获取任务,当队列已满时,不能向其中添加任务。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391 ...
JUC之线程池的标准创建方式
[TOC]
JUC之线程池的标准创建方式 因为使用Executors快捷创建线程池在使用时会有严重的潜在问题,因此在实战使用时一般不使用快捷创建线程池的方式在创建线程池,而是使用ThreadPoolExecutor的标准构造器去构建线程池。Executors工厂类中创建线程池的快捷工厂方法实际上是调用 ThreadPoolExecutor(定时任务使用ScheduledThreadPoolExecutor) 线程池的构造方法完成的。
ThreadPoolExecutor构造方法有多个重载版本,较重要的一个构造器包含七个参数,如下:
1234567public ThreadPoolExecutor(int corePoolSize,//核心线程数,即使线程空闲也不会回收 int maximumPoolSize,//最大线程数 long keepAliveTime,//线程的最大空闲时长 TimeUnit u ...
Elasticsearch之基本API操作
Elasticsearch之基本API操作索引操作创建索引:使用PUT请求,http://localhost:9200/ + 索引名称
创建索引的映射:PUT, http://localhost:9200/+索引名称+/_mapping
1234567891011121314151617181920212223242526272829{ "properties": { "name":{ "type": "text", "index": true }, "sex":{ "type": "keyword", "index": true }, "tel":{ "t ...
JUC之Executors的4种快捷创建线程池的方法
[TOC]
JUC之Executors的4种快捷创建线程池的方法Java通过Executors工厂类提供了4种快捷创建线程池的方法,具体如下:
1234newSingleThreadExecutor()//创建只有一个线程的线程池newFixedThreadPool(int nThreads)//创建固定大小的线程池newCachedThreadPool()//创建一个不限制线程数量的线程池,任何提交的任务都将立即执行,但是空闲线程会得到及时回收newScheduledThreadPool()//创建一个可定期或者延时执行任务的线程池
newSingleThreadExecutor创建“单线程化线程池”1234567891011121314151617181920212223242526272829303132333435import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.atomic.AtomicInteger;pu ...
JUC线程池之线程池架构
JUC线程池之线程池架构在多线程编程中,任务都是一些抽象且离散的工作单元,而线程 是使任务异步执行的基本机制。随着应用的扩张,线程和任务管理也 变得非常复杂。为了简化这些复杂的线程管理模式,我们需要一个 “管理者”来统一管理线程及任务分配,这就是线程池。
线程池的架构图大致如下:
Executor Executor是Java异步目标任务的“执行者”接口,其目标是执行 目标任务。“执行者”Executor提供了execute()接口来执行已提交的 Runnable执行目标实例。Executor作为执行者的角色,其目的是提供 一种将“任务提交者”与“任务执行者”分离开来的机制。
只包含一个函数式方法:
1void execute(Runnable command)
ExecutorService 继承于Executor。他是Java异步目标任务的“执行者服务”接口,对外提供异步任务的接受服务。
提 供了“接收异步任务并转交给执行者”的方法,如:
1234//向线程池提交单个异步任务<T> Future<T> submit(Callable<T> ...
JUC之创建线程的几种方式
[TOC]
JUC之创建线程的几种方式继承Thread类创建线程 通过继承Thread类创建一个线程类,新的 线程子类重写了Thread的run()方法,实现了用户业务代码的并发执行,具体如下:
1234567891011121314151617181920212223242526public class javaJUCstudy { public static final int MAX_TURN = 5; public static String getCurThreadName(){ return Thread.currentThread().getName(); } static int threadId = 1; public static void main(String[] args) { Thread h; for (int i = 0; i < 2; i++) { h = new TestThread(); ...
JUC之进程与线程
[TOC]
JUC之进程与线程进程什么是进程 什么是进程呢?简单来说,进程是程序的一次启动执行。什么是 程序呢?程序是存放在硬盘中的可执行文件,主要包括代码指令和数 据。一个进程是一个程序的一次启动和执行,是操作系统将程序装入 内存,给程序分配必要的系统资源,并且开始运行程序的指令。
进程与程序是什么关系呢?同一个程序可以多次启动,对应多个 进程。比如,多次打开Chrome浏览器程序,对应的就是多个Chrome进程。
进程的组成 进程是程序执行和系统进行并发调度的最小单位。一般来说一个进程是由程序段、数据段和程序控制块三部分组成。进程结构图如下:
程序段 程序段一般也被称为代码段。代码段是进程的程序指令在内存中的位置,包含需要执行指令的集合。
数据段 数据段是进程的操作数据在内存中的位置,包含需要操作的数据集合。
程序控制块 程序控制块(Program ControlBlock,PCB)包含进程的描述信息和控制信息,是进程存在的唯一标志。
描述信息:主要包括进程ID和进程名称,进程ID是唯一的,代表进程的身份;进程状态,比如运行、就绪、阻塞;进程优先 ...
呼啸山庄读后感
呼啸山庄读后感《呼啸山庄》是一部在英国十九世纪文坛上焕发异彩的天才之作。它狂放不羁的浪漫主义风格蕴含在阴冷而暴力,神秘怪诞又隐隐约约透出神圣温情的背景中,整个场景是一个封闭的小社会——两个孤立的山庄和开放的大自然与荒原,书中人物身上体现出爱与恨两种极端,极度的爱中混杂着极度的恨,使小说在颤栗中呈现出极为强烈的戏剧化色彩。
英国著名作家毛姆曾评论说 :“我不知道还有哪一部小说其中爱情的痛苦、迷恋、残酷、执著,曾经如此令人吃惊地描述出来。《呼啸山庄》使我想起埃尔·格里科的那些伟大的绘画中的一幅,画上是一片乌云下的昏暗的荒瘠土地的景色,雷声隆隆拖长了的憔悴的人影东歪西倒,被一种不是属于尘世间的情绪弄得恍恍惚惚,他们屏息着。铅色的天空掠过一道闪电,给这一情景加上最后一笔,增添了神秘的恐怖之感。”
《呼啸山庄》出版于1847年,是英国女作家艾米莉·勃朗特唯一的一部小说作品,初问世时,它颇受冷落;但随着岁月的流逝,其别具一格的艺术魅力征服了越来越多的读者。而今,在西方文学的经典书单中,它已与《战争与和平》这样的巨著分庭抗礼了。
拿着《呼啸山庄》这本书,我就在想它为什么以呼啸山庄命名?呼啸二字又代表 ...
JVM之java虚拟机中对象创建过程
[TOC]
JVM之java虚拟机中对象创建过程我们平常创建一个对象,仅仅只是使用new关键字new一个对象,这样一个对象就被创建了,但是在我们使用new关键字创建对象的时候,在java虚拟机中一个对象是如何从无到有被创建的呢,我们接下来就来谈谈在java虚拟机中一个对象的创建过程(仅指我们平常使用的对象,不包括数组对象和Class对象)。
对象的内存布局在了解对象的创建过程之前,我们先说说对象的内存布局,在HotSpot虚拟机中,对象在堆中的存储布局可以划分为三部分:对象头(Header)、示例数据(Instance Data)和对齐填充(Padding)。
对象头(Header)HotSpot虚拟机对象的对象头包括两类信息。
第一类是用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
对象头的另一部分是类型指针,即对象指向它的类型元数据的指针,java虚拟机通过这个指针来确定该对象是哪个类的实例。
如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对 ...
JVM之java虚拟机内存分布
[TOC]
JVM之java虚拟机内存分布Java虚拟机在执行java程序的过程中会把它所管理的内存划分为如下若干个不同的数据区域。
1.程序计数器程序计数器是线程私有的,它占用的空间相对较小,用来记录当前线程字节码执行到哪一步。字节码解释器通过改变这个计数器的值来获取当前线程下一步需要执行的指令,以此来确保在多条线程相互切换之后还能正确的回到切换之前执行的那一步指令。
需要注意的是如果当前线程正在执行的是一个Java方法,那么程序计数器记录的就是正在执行的虚拟机字节码指令的地址;如果当前线程正在执行的是本地(Native)方法,那此时程序计数器的值为空(Undefined)。
并且程序计数器所在的内存区域是在《java虚拟机规范》中唯一一个没有规定任何OutOfMemory Error情况的区域。
2.堆Java堆(Java Heap)是虚拟机所管理的内存中最大的一块,它是所有线程共享的一块内存区域。Java堆的目的就是为了存放Java对象,几乎所有的Java对象实例都在Java堆中分配内存。java堆是垃圾收集器工作的主要区域。
Java堆既可以被设置为固定大小,也可以被设置为可 ...