方法我们通过继承Thread类和实现runnable接口或者callable接口三种方式实现。

继承Thread类实际上也是实现了runnable接口,被继承的类主要是实现run()方法,通过start()方法调用。

而callable接口是属于Executor

对比与Runnable接口功能的区别是:
(1).Callable可以在任务结束后提供一个返回值,Runnable没有这个功能
(2).Callable中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常
(3).运行Callable可以拿到一个Future对象,Future独享表示异步计算的结果,它提供了检查计算是否完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数
的返回值,在这种情况下,就可以使用Future来监视目标线程调用call()方法的情况,放调用Future的get()方法以获取结果时,当前线程就会阻塞,知道call()方法结束返回结果。 我们可以使用多线程来达到最优效率,但是,线程不是越多就越好,线程过多,创建和销毁就会消耗系统的资源,也不方便管理。

除此之外,多线程还会造成并发问题,线程并发数量过多,抢占系统资源从而导致阻塞。

我们将线程放入线程池,由线程池对线程进行管理,可以对线程池中缓冲的线程进行复用,这样,就不会经常去创建和销毁线程了,从而省下了系统的资源。

线程池能够有效的控制线程并发的数量,能够解决多线程造成的并发问题。

ThreadPoolExecutor

Java提供了ThreadPoolExecutor线程池类,他的构造方法有四个,主要是参数不同

corePoolSize为的线程池最大核心线程数量

maximumPoolSize为最大线程池数量

keepAliveTime 当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间

unit 存活时间的单位

workQueue 存放线程的工作队列

handler:超出线程范围和队列容量的任务的处理程序(拒绝策略)

当线程放入线程池中,当线程的数量已经等于最大的核心线程数量,此线程就会放入线程队列当中,等待线程的调用。

线程池的最大线程数(线程总数,maximumPoolSize)= 核心线程数(corePoolSize)+非核心线程数

核心线程是永远不会被线程池丢弃回收(即使核心线程没有工作),非核心线程则是超过一定时间(keepAliverTime)则就会被丢弃

Excutors工具类

java提供了Excutors工具类,适用于一下小项目,对于一些大型程序还是需要自己创建ThreadPoolExecutor类,因为Excutors可能会造成OOM(堆内存溢出)

FixedThreadPool 和 SingleThreadExecutor : 允许请求的队列长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致OOM。
CachedThreadPool 和 ScheduledThreadPool : 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致OOM。
方法 说明
newFixedThreadPool(int nThreads) 创建固定大小的线程池
newSingleThreadExecutor() 创建只有一个线程的线程池
newCachedThreadPool() 创建一个不限线程数上限的线程池,任何提交的任务都将立即执行
newScheduledThreadPool(int nThreads) 创建一个支持定时、周期性或延时任务的限定线程数目的线程池
newSingleThreadScheduledExecutor() 创建一个支持定时、周期性或延时任务的单个线程的线程池

线程池获取执行结果

把线程提交给线程池中,有两种方法,一种是submit,另外一种则是execute

execute没有返回值,性能会好很多,submit返回一个Future对象,如果想知道线程结果就使用submit提交,而且它能在主线程中通过Future的get方法捕获线程中的异常。

这两种方法的参数必须要实现runnable接口或者是callable对象

线程池的处理结果、以及处理过程中的异常都被包装到Future中,并在调用Future.get()方法时获取,执行过程中的异常会被包装成ExecutionException。

关闭线程池

可以通过shutdown()或者shutdownNow()方法

shutdown() :   不再接受新的任务,之前提交的任务等执行结束再关闭线程池

shutdownNow() :不再接受新的任务,试图停止池中的任务再关闭线程池,返回所有未处理的线程list列表。

Semaphore 的使用方式

Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。(并发控制信号量)

我们可以在主要执行任务的call()方法或者run()方法中使用semaphore来控制并发。

semaphore的构造方法有两个

第一个构造方法的参数为同一时刻允许线程进入的个数,如果为1,就相当于单个线程。

第二个构造方法的参数为线程公平性isFair

 isFair 的意思就是,是否公平,获得锁的顺序与线程启动顺序有关,就是公平,先启动的线程,先获得锁。isFair 不能100% 保证公平,只能是大概率公平。

 isFair 为 true,则表示公平,先启动的线程先获得锁。

在 semaphore.acquire() 和 semaphore.release()之间的代码,同一时刻只允许制定个数的线程进入, 因为semaphore的构造方法是1,则同一时刻只允许一个线程进入,其他线程只能等待。

acquire:

线程池ThreadPoolExecutor的使用方法的更多相关文章

  1. [3]java1.8线程池—ThreadPoolExecutor

    Wiki 上是这样解释的:Thread Pool 作用:利用线程池可以大大减少在创建和销毁线程上所花的时间以及系统资源的开销! 下面主要讲下线程池中最重要的一个类 ThreadPoolExecutor ...

  2. 线程池ThreadPoolExecutor的学习

    我们知道,ExecutorService是一个抽象出线程池的一个接口,然后我们在使用线程池的时候,用的是Executors工具类中的一系列newCachedThreadPool() 等类似的方法,这些 ...

  3. 硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理

    前提 很早之前就打算看一次JUC线程池ThreadPoolExecutor的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章.之前在分析扩展线程池实现可回调的Future时候曾经提到并发 ...

  4. 12.ThreadPoolExecutor线程池原理及其execute方法

    jdk1.7.0_79  对于线程池大部分人可能会用,也知道为什么用.无非就是任务需要异步执行,再者就是线程需要统一管理起来.对于从线程池中获取线程,大部分人可能只知道,我现在需要一个线程来执行一个任 ...

  5. java 线程池ThreadPoolExecutor 如何与 AsyncTask() 组合使用。

    转载请声明出处谢谢!http://www.cnblogs.com/linguanh/ 这里主要使用Executors中的4种静态创建线程池实例方法中的 newFixedThreadPool()来举例讲 ...

  6. java线程池ThreadPoolExecutor使用简介

    一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...

  7. java线程池ThreadPoolExecutor理解

    Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...

  8. 线程池ThreadPoolExecutor、Executors参数详解与源代码分析

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. ThreadPoolExecutor数据成员 Private final Atom ...

  9. 线程池ThreadPoolExecutor

    线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int maxi ...

随机推荐

  1. python小例子(一)

    参考链接:https://zhuanlan.zhihu.com/p/83998758?utm_source=qq&utm_medium=social&utm_oi=7282008528 ...

  2. vue的数据双向绑定

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. 在docker中创建使用MySQL,并实现远程连接navicat

    在 docker 中使用 mysql 安装完docker之后,在命令行中输入docker images可以查看自己创建的image(安装下载docker的教程很多了,大家需要可以去查一下就可以了)这里 ...

  4. 二:Mysql库相关操作

    1:系统数据库 information_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息.列信息.权限信息.字符信息等.performance_schema: My ...

  5. 深入理解.NET Core的基元(二) - 共享框架

    原文:Deep-dive into .NET Core primitives, part 2: the shared framework 作者:Nate McMaster 译文:深入理解.NET Co ...

  6. Vue引入插件

    引入Element ui 1.在当前目录下,运行:npm i element-ui -S  2.在src/main.js中添加代码 import ElementUI from 'element-ui' ...

  7. Ambari 集群时间同步配置教程

    本文原始地址:https://sitoi.cn/posts/27560.html 步骤 在时间同步主节点创建 ntp.conf 文件 在时间同步从节点上创建 ntp.conf 文件 修改所有节点时区 ...

  8. vue H5页面手机端 利用canvas 签名

    签名首先用一个canvas标签,上面加三个代码,分别是点击,移动,离开.这里点击是开始画笔的地方,如果不加@touchstart 笔头会发生偏移,可以试试. @toucheend也是如此.尾巴也会出现 ...

  9. Spring 动态代理 之 but was actually of type 'com.sun.proxy.$Proxy14 Exception

    今天在写Spring的引介代理的时候,报了一个错: Exception in thread "main" org.springframework.beans.factory.Bea ...

  10. [开源] gnet: 一个轻量级且高性能的 Golang 网络库

    Github 主页 https://github.com/panjf2000/gnet 欢迎大家围观~~,目前还在持续更新,感兴趣的话可以 star 一下暗中观察哦. 简介 gnet 是一个基于 Ev ...