java的多线程的概念,向来都是很复杂、笼统、抽象的。现实世界只有将知识点抽象事后才能有效的传播,可是传播的过程当中,只有将抽象的知识点具象化,咱们才能习得。因此咱们会将个别内容点进行一个具象化进而解剖。当咱们理解完了以后最终将其抽象成一个个名词:多线程、资源、锁等。java
本文仅从如下的范围内容来谈谈java的多线程。程序员
官方解释:线程是一个单一的顺序控制流程。编程
线程分主线程、子线程。由主线程来建立子线程来执行各类任务。多线程
举例说明:以动漫“火影忍者”举例说明,主线程就比如每个忍者,他们构成了最基本的忍者世界,一个忍者能够按照任务的缓急、难易程度同时执行多个任务。同时忍者也能分身(调用自身查克拉)来分担自身的任务,这就比如,忍者世界观中的忍者主体,基本等同于程序中的主线程。主线程没了,分身则主观上不可控,就消失了。异步
由上图可见,主线程与子线程的关系和忍者与分身的是很类似,也就是说,主线程能作的事,咱们都能让子线程帮咱们作。忍者本身能作的事也能去靠分身去作。接下来,咱们来看两段代码。工具
//代码一
public static void main(String[] args) {
System.out.println("Hello World!");
}
复制代码
//代码二
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println("Hello World!");
});
thread.start();
}
复制代码
代码一和代码二最终的结果都是只作了一件事,向控制台输出“Hello World!”。可是代码一是由主线程去作的;代码二是由主线程建立的子线程去作的。这里咱们能够看出,主线程和子线程的本质上区分并不大,由于它们都执行相同的逻辑,这一点上并无进行区分。性能
程序若是都是按照单个线程的话,那么全部任务的执行均是按照顺序来进行(串行执行)。优化
而多线程的做用是能够安排不一样的线程执行不一样的任务。spa
上图是一个理论值,咱们在某些任务密集的场景下,多线程的执行效率多数状况下可能高于单线程的执行。线程
为何说是可能,由于这里建立子线程是会消耗性能的,也带有时间消耗,若是设置不合理,单单建立子线程的时间成本就远大于执行任务的时间成本,这一点要结合实际场景进行考虑。
举例说明:火影里的忍者也不会接到一批任务就立刻分身去一个个的作,他们也得结合任务的实际状况来考虑使用分身。
java中的资源能够理解为,一个实例或基础数据类型的变量的任何操做。实例或变量在这里不能彻底算作资源,由于根据面向对象编程中的封装性,代码中直接将实例暴露出来给非本类的实例进行操做是一个大忌。
这里咱们从如下资源和线程的关系进行解剖。
从这里看,1和3没什么问题。由于这种机制下咱们确保了一个资源被一个线程执行(等同于一个任务被一个忍者(本体或分身都可)执行)。可是2和4就出现了一个现象,同一个资源被多个线程所操做,若是不加以控制,则会出现指定以外的执行结果或者直接产生死锁。
举例说明:两个忍者都执行了同一个任务,去杀死邻国的头目,咱们假设忍者A过去杀死了头目,忍者B后去的,发现头目死了,那他接下来怎么办?算任务失败仍是算完成了?
固然忍者B最后确定仍是回去复命了,也算他任务成功,这是任务自己的规则和秩序所决定的,可是程序的世界是无秩序,须要程序员经过代码去打造这个无序的世界从而造成秩序。
资源自身必定要包含约束性和规则性才能被正确的使用。
java自己提供了资源被多个线程调度的控制方式。
咱们经过一张图表来概况了解一下。
对于资源的控制的方式无非就是一个“锁” 字。现实当中处处充斥着这样的例子,例如一个城市的市长,按照规定只能有一个,谁上任,那么市长这个资源位就被谁“锁”住了。可是程序世界中的“锁”和现实世界中的“锁”差异很大。
java中有关于锁的内容很是多,咱们这里先用一张图来简要介绍一下,之后再着重篇幅去介绍每一个锁的相关特性。
用一段话形容线程和资源的关系那就是。某我的(线程)去作(调度)某件有要求和规则(锁策略)的事(资源);根据这件事(资源)的要求和规则(锁策略)去约束作这个事人(线程)的作法。
咱们用各类锁策略去保证资源能被正确的使用。这里咱们还缺一个角度,那就是从线程的角度去调度资源。
咱们用一个问题开头来展开对话。
这就是一个线程池的雏形,线程池的雏形具备如下的基本特性
咱们来解刨线程池的最全的配置信息:
按照咱们常规的设置
BlockingQueue > maximumPoolSize ≥ corePoolSize
总结:线程池就是多个线程来调度多个资源时所优化的一种多维度的策略,它的核心就是线程的复用以及资源的缓冲存储。
类或关键字 | 简要介绍 | 使用的对象 |
---|---|---|
synchronized | 做用于方法或代码块中实现线程的同步性 | 资源 |
Atomic包 | 原子性控制变量或实例 | 资源 |
ReentrantLock | 做用于方法中,实现线程的同步性 | 资源 |
Semaphore | 做用于方法中,限制方法的线程最大调度数 | 资源 |
Phaser | 做用于方法中,设置线程必须调度的数量 | 资源 |
Object.wait() | 做用于同步的方法中,使当前调度的进程等待 | 资源 |
Object.notifyAll()或notify() | 做用于同步的方法中,唤起当前处于等待状态的调度线程 | 资源 |
Runable | 线程中调度无返回结果的资源 | 线程 |
Callable | 线程中调度有返回结果的资源 | 线程 |
Future | 线程执行有返回结果的资源的接受方 | 线程 |
Executor | 建立线程池的工厂类(慎用) | 线程 |
ThreadPoolExecutor | 线程池的实现类 | 线程 |
ExecutorService | 线程池的基础类 | 线程 |
CompletionService | 异步处理带返回结果的线程池 | 线程 |
ScheduledExecutorService | 处理定时任务的线程池 | 线程 |
Fork-Join | 分治思想处理批量任务 | 线程 |