java线程池
1.程序,进程,线程区别
程序:含有指令和数据的文件,被存储在磁盘或者数据存储设备中,静态的代码。
进程:是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。程序在执行时,将会被操作系统载入内存中。
线程:是比进程一个更小的执行单位,一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程时,或是各个线程之间切换工作时,负担要比进程小的多,所以称为轻量级进程。
线程与进程最大的不同在于各个进程是独立的,而线程则不一定,因为同一进程的线程极有可能会相互影响。从另一层面来说,进程属于操作系统的范畴
2.Thread类中的start()和run()方法有什么区别
run只是Thread类的一个普通方法,当你调用run方法,你的程序自始至终只有主线程这一个线程,没有新线程启动
start方法用来启动新创建的线程,这时候线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run方法。
3.实现多线程有几种方式
答:四种,追其底层就是基于runnable接口
1.继承thread类,重写run方法
2.实现runnable接口,重写run方法
3.实现callable接口,重写call方法,配合futuretask使用
4.基于线程池去构建线程
这里面实现runnable和callable接口都可以,由ExecutorService去创建线程
4.为什么不建议Excecutors来构建线程池
在jdk1.5的时候doug lea针对于线程池提供了一个工具类Excecutor
1.FixedThreeadPool
当我们使用Excecutors去创建FixedThreadPool
发现构造方法里面的参数创建的队列是LinkedBlockingQueue,是一个链表阻塞队列,如果用这个线程池去执行任务,如果任务过多就会不断的加入到队列中,任务越多占用的内存越多,最终可能会耗尽,导致OOM(内存溢出)异常。
2.SingleThreadExcecutor
当我们使用Excecutors去创建SingleThreadPool
这个构造方法里面的参数也是LinkedBlockingQueue,任务过多也会造成OOM(内存溢出异常)。
总结:除了能造成OOM异常之外,比如NewCacheThreadPool不会造成OOM,只会创建线程占用CPU资源,CPU的资源100%被占用,程序就会卡死。(线程是由CPU分配的最小时间单位,线程执行需要CPU去调度他)我们使用Excecutors来创建线程池不能自定义线程池的名字以及参数,不利于排查问题,所以建议直接使用ThreadPoolExcecutor来定义线程池,这样可以灵活控制。
5.线程池的原理,以及核心参数
线程池核心参数的概念
corePoolSize---核心线程数
MaximumPoolSize---最大线程数
keepAliveTime----活跃时间
workQueue-----阻塞队列
RejectedExcecutionHandler----拒绝策略
当提交一个新任务到线程池,具体执行流程如下:
步骤:
1.当我们提交任务,线程池会根据CorePoolSize(核心线程数)大小创建很多个线程去执行任务
2.当任务数量多于corePoolSize(核心线程数)数量时,后续的任务会进入阻塞队列阻塞排队
3.当阻塞队列也满的时候,将会继续创建(MaximumPoolSize-corePoolSize)数量来执行任务,如果任务处理完成,(MaximumPoolSize-corePoolSize)额外创建的线程等待keepAliveTime后被自动销毁。
4.达到(MaximumPoolSize),阻塞队列也是满的情况下,那么应该根据不同的拒绝策略对应处理
6.线程池的拒绝策略有哪些
主要有四种拒绝策略
1.AbortPolicy:默认策略,直接丢弃任务,抛出异常
2.CallerRunsPolicy:只用调用者所在的线程来处理任务
3.DiscardOldestPolicy:丢弃等待队列中最旧的任务,并执行当前的任务
4.DiscardPolicy:直接丢弃任务,也不抛出异常
7.Java线程池中队列常用类型
1.ArrayBlockingQueue
基于数组结构的有界阻塞队列,按FIFO原则,对元素进行排序
2.LinkedBlockingQueue
基于链表结构的阻塞队列,按FIFO原则,对元素进行排序,吞吐量一般要高于ArrayBlockingQueue
3.SynchronousQueue
不存储元素的阻塞队列
8.什么时候用线程池
当单个任务处理时间比较短,需要处理的任务数量很大时。
9.线程池的优势
重用存在的线程,减少线程的创建,消亡的开销,提高性能
提高响应速度,当任务到达时,任务不需要等到线程创建就能立刻执行
提高线程的可管理性,可统一分配,调优和监控
10.线程池的意义
线程是稀缺资源,他的创建和销毁是一个相对偏重且耗资源的操作,而java线程依赖于内核进程,创建线程需要操作系统状态切换。为了避免资源过度消耗要设法重用线程执行多个任务。线程池就是一个线程缓存,负责对线程进行统一分配,调优和掌控。