线程模型

线程模型分为两类,用户级线程(ULT)和内核级线程(KLT)

用户级线程(ULT):user level threads,系统内核对ULT无感知,线程的创建和调度都由用户级APP进程管理;即APP自行管理的线程,就是用户级线程

内核级线程(KLT):kernel level threads,线程的创建,调度和切换上下文等,都由操作系统内核管理

如图所示,ULT模型中,每个进程创建的线程,均由自身进程维护管理,而KLT模型中,进程创建的线程,由系统内核进行维护管理。

​在执行的区别之上,ULT和KLT最大的区别就是:ULT线程的调度不需要内核直接参与,控制简单,创建和销毁线程、线程切换代价等线程管理的开销比内核线程少得多。但是其资源调度按照进程进行,不能利用系统的多核处理,多个处理器下,同一个进程中的线程只能在同一个处理器下分时复用;KLT由内核进行调度,当有多个处理器时,一个进程的多个线程可以同时执行,但是KLT线程的创建和切换等开销很大。

​Java线程是依赖于系统内核,通过JVM调用系统库创建内核线程。Java的Thread和内核线程呈 1:1映射关系。by the way,这也是为什么我们需要线程池进行线程池化管理的原因。

线程池

基础概念

​线程是程序运行的载体,说白了就是拥有cpu多长时间的执行权。而由于java线程是内核级线程带来的昂贵开销成本,在平时运用场景中我们也经常使用线程池对线程进行池化管理。线程池能为我们带来3大好处:

复用已创建的线程,降低创建销毁线程等带来的资源消耗

提高响应速度。线程早已创建好,不需要在等待线程创建就可以直接使用

可管理线程。由于线程是稀有资源,不能无限创建,因此用线程池能对线程进行统一规划,监控和分配

在线程池中,有几项概念最为重要:核心线程数,最大线程数,等待队列,饱和策略。它们的执行过程如下图。

为加强记忆,可以用工厂干活的方式理解。把核心线程数看作是正式工,当来了一堆任务的时候,正式工陆续开始干活,当任务增多的时候,正式工们手头上的任务还没干完,于是先放阻塞队列等待待会儿处理;后来任务量暴涨,阻塞队列也满了,于是就请一些临时工来干活,于是,正式工数+临时工数 = 最大线程数;再后来线程数持续增长,最大线程数也满了,只能做一些饱和策略限制任务的提交了。

线程池的使用

​我们可以通过new ThreadPoolExecutor的方式创建线程池。

//构造方法

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue)

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

ThreadFactory threadFactory)

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

RejectedExecutionHandler handler)

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

其中的参数需要说明下:

corePoolSize:核心线程数。线程池在最初阶段,池中线程数为0,当接收到一个任务后,就创建一个线程。即使之前的线程执行完毕空闲,新任务提交过来,依然会创建线程。直到创建线程到核心线程数。如果调用了prestartAllCoreThreads方法,那么线程池会预先创建好线程。

BlockingQueue: ⽤于保存等待执⾏的任务的阻塞队列,可参考JUC的7种阻塞队列,这里不再赘述

maximumPoolSize:线程池允许创建的最⼤线程数。如果队列满了,并且已创建的线程数⼩于最⼤线程数,则线程池会再创建新的线程执⾏任务

TimeUnit:线程活动保持时间的单位

keepAliveTime:线程活动保持时间。当线程池中创建的线程数量超过核心线程数,且有线程空闲超过该时间,空闲线程将会被回收至核心线程数大小。当设置为0,即只要线程空闲就立即回收

ThreadFactory:⽤于设置创建线程的⼯⼚,可以通过线程⼯⼚给每个创建出来的线程设置更有意义的名字。附录附上线程工厂的用法例子。

RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取⼀种策略处理提交的新任务。这个策略默认情况下是AbortPolicy。在JDK1.5中Java线程池框架提供了以下4种策略。

AbortPolicy:直接抛出异常。

CallerRunsPolicy:当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。

DiscardOldestPolicy:线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。

DiscardPolicy:不处理,丢弃掉。

当然也可以自定义,在附录举了一个demo可参考。

举上一个较为完整的线程池创建示例

BlockingQueue workQueue = new ArrayBlockingQueue(5);

ThreadPoolExecutor threadPoolExecutor =

new ThreadPoolExecutor(5, 10, 1000, TimeUnit.MILLISECONDS, workQueue, new ThreadPoolExecutor.AbortPolicy());

线程池的工作状态

线程池共有5种生命状态:RUNNING,SHUTDOWN,STOP,TIDYING,TERMINATED

RUNNING:接受新任务并处理排队的任务

SHUTDOWN:不接受新任务,但处理排队的任务

STOP:不接受新任务,不处理排队的任务,中断正在进行的任务

TIDYING:所有任务都已终止,workerCount为零,将运行terminate()钩子方法

TERMINATED:线程池终止

线程池提交任务的方式有两种,分别为execute()和 submit()⽅法。

execute()⽅法⽤于提交不需要返回值的任务,⽆法判断任务是否被线程池执⾏成功。

submit()⽅法⽤于提交需要返回值的任务。线程池会返回⼀个future类型的对象,可通过future对象判断线程是否执行成功,获取返回值等。

线程池关闭的方式也有两种,shutdown()和shutdownNow()⽅法可关闭线程池。它们的原理是遍历线程池中的⼯作线程,然后逐个调⽤线程的interrupt⽅法来中断线程,所以⽆法响应中断的任务可能永远⽆法终⽌。

区别在于,shutdownNow 更改状态成STOP,然后尝试停⽌所有的正在执⾏或暂停任务的线程,并返回等待执⾏任务的列表,⽽shutdown更改状态成SHUTDOWN状态,然后中断所有没有正在执⾏任务的线程,正在执行的线程会继续执行完毕。

1.线程池设置多少合适:

2. 线程工厂的demo

/**

* 实现线程工厂的接口,然后实现自定义内容。重写newThread方法

*/

public class MyThreadFactory implements ThreadFactory {

private static int COUNTER = 0;

private static String THREAD_PREFIX = "myThread";

@Override

public Thread newThread(Runnable r) {

int i = COUNTER++;

return new Thread(r, THREAD_PREFIX + i);

}

//使用

public static void main(String[] args) {

MyThreadFactory myThreadFactory = new MyThreadFactory();

Thread thread = myThreadFactory.newThread(new Runnable() {

@Override

public void run() {

}

});

thread.start();

}

}

2. 自定义饱和策略

//需要实现RejectedExecutionHandler,重写rejectedExecution方法

class MyRejected implements RejectedExecutionHandler {

public MyRejected() {

}

@Override

public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

System.out.println("现线程池中的情况为:" + executor.getActiveCount());

System.out.println("当前被拒绝任务为:" + r.toString());

}

}

java线程提交_从Java线程到线程池相关推荐

  1. java runnable线程锁_多线程 java 同步 、锁 、 synchronized 、 Thread 、 Runnable

    线程 1 线程概述 1.1 什么是线程 v  线程是程序执行的一条路径, 一个进程中可以包含多条线程 v  一个应用程序可以理解成就是一个进程 v  多线程并发执行可以提高程序的效率, 可以同时完成多 ...

  2. java group类_浅析Java中线程组(ThreadGroup类)

    Java中使用ThreadGroup类来代表线程组,表示一组线程的集合,可以对一批线程和线程组进行管理.可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的 ...

  3. java线程概念_《Java基础知识》Java线程的概念

    按照规划,从本篇开始我们开启『并发』系列内容的总结,从本篇的线程开始,到线程池,到几种并发集合源码的分析,我们一点点来,希望你也有耐心,因为并发这块知识是你职业生涯始终绕不过的坎,任何一个项目都或多或 ...

  4. postgres 支持的线程数_为什么 Java 坚持多线程不选择协程?

    先说结论:协程是非常值得学习的概念,它是多任务编程的未来.但是Java全力推进这个事情的动力并不大. 先返回到问题的本源.当我们希望引入协程,我们想解决什么问题.我想不外乎下面几点: 节省资源,轻量, ...

  5. java 多线程状态_总结Java中线程的状态及多线程的实现方式

    线程的状态线程状态图: 说明: 线程共包括以下5种状态. 1. 新建状态(New) : 线程对象被创建后,就进入了新建状态.例如,Thread thread = new Thread(). 2. 就绪 ...

  6. 纯java分布式内存数据库_最新Java岗面试清单:分布式+Dubbo+线程+Redis+数据库+JVM+并发...

    最近可能有点闲的慌,没事就去找面试面经,整理了一波面试题.我大概是分成了Java基础.中级.高级,分布式,Spring架构,多线程,网络,MySQL,Redis缓存,JVM相关,调优,设计模式,算法与 ...

  7. java 线程状态_浅析Java中的线程状态

    一.线程的5种状态 众所周知,Java的线程状态有5种,分别对应上图中五种不同颜色,下面对这5种状态及状态间的转化做相应的解释: 1. 初始化状态:新建一个线程对象 2. 可运行状态:其他线程调用了该 ...

  8. java vector 线程安全_关于Vector到底是不是 线程安全的 问题

    线程安全,在java的多并发编程中是重要概念,意思是,多个线程同时操作一个对象,在各种不同情况下,都不会造成不同的后果. 一个经典问题,Vector到底是不是线程安全的? 很多人都会回答,是,vect ...

  9. java 线程管理框架_实现 Java 多线程并发控制框架

    所面临的问题 图 1. 线程场景 这幅图中节点代表一个 single Thread,边代表执行的步骤. 整幅图代表的意思是,ROOT 线程执行完毕后执行 T1 线程,T1 执行完毕后并发的执行 T2 ...

最新文章

  1. 联想服务器升级微码文件,ThinkPad如何升级硬盘微码程序(适用于SL系列机器)
  2. Linux 磁盘分区 Fdisk
  3. 9读书1-我在义务发财(1)
  4. collectd 5.7.2 发布,系统监控和统计工具
  5. TypeScript:Web开发
  6. [转]中国象棋谚语大全
  7. android apk很大,从Android Studio生成的Apk文件太大
  8. python爬取拉勾网_Python搭建代理池爬取拉勾网招聘信息
  9. Python制作当年第一款真正意义上的手机游戏——贪吃蛇游戏
  10. Android拍照,照片会自己旋转
  11. 电子钱包CPU卡和PSAM卡消费密钥装载分析
  12. Java 设计模式总结及六大设计原则
  13. 软工实践 - 第二十二次作业 项目测评(团队)
  14. 企业微信欢迎语如何将链接转换为图文卡片形式?
  15. make与makefile
  16. python repair修复功能在哪_linux下repair filesystem模式修复方法
  17. BiliBili快捷键
  18. WPS 查找历史版本记录
  19. PTA1024-C语言-科学计数法
  20. [CSP-S模拟测试]:影魔(树状数组+线段树合并)

热门文章

  1. java jar killed_容器中Java 程序OOMKilled原因浅析
  2. python中可变参数怎么传递的呢_在python中,你可以在命名参数后传递可变参数吗?...
  3. java递归api_javaAPI_IO流基础_递归使用
  4. c# opencv 轮廓检测_C#中OpenCVSharp实现轮廓检测
  5. qq数据泄露_真良心,腾讯这个app竟然能查账号泄露
  6. 转译和编译_10个有趣又能编译为JavaScript的语言,你用过哪些?
  7. 工业交换机安全性能的必要性
  8. 【渝粤教育】国家开放大学2018年秋季 2604T城市轨道交通行车组织 参考试题
  9. 三星q90r如何升级系统_看尚电视强制升级风行系统,如何安装第三方软件?
  10. 蓝桥杯基础模块2:蜂鸣器继电器