序:最近在回忆熟悉以往的知识,简单记录,这篇是线程的简单入门。
java线程入门
1.线程生命周期
创建,就绪,运行,堵塞,销毁
2.创建线程的三种方式
1.继承Thread
优点:创建简单
缺点:单继承的限f制-无法继承其它父类,同时不能实现资源共享
2. 实现Runnable,覆写run方法
优点:可继承其它类,多线程可共享一个Thread对象,推荐使用
缺点:编程方式稍微复杂
3.实现Callable<T>,覆写call方法
优点:有返回值,可以抛出异常
3.创建线程池的两种方式
3.1.通过Executors工厂方法创建,Executors有五种类型
类型 | 解释 |
---|---|
newSingleThreadExecutor() | 创建使用单个线程的线程池, 提供了单个后台线程 |
newFixedThreadPool(n) | 创建使用固定线程数的线程池,提供了固定大小线程池,内部使用无界队列。 |
newCachedThreadPool() | 创建一个会根据需要创建新线程的线程池,提供了无界线程池,可以进行自动线程回收 |
newScheduledThreadPool(n) | 创建拥有固定线程数数量的定时线程任务的线程池 |
newSingleThreadScheduledExecutor() | 创建只有一个线程的定时线程任务的线程池 |
3.2.通过ThreadPoolExcutor()自定义创建
4. ThreadPoolExecutor相关参数解释
public ThreadPoolExecutor(int corePoolSize, //核心池大小
int maximumPoolSize,//线程池最大线程数
long keepAliveTime,//线程没有任务时最多保持多久时间会终止,默认情况下,当线程池中线程数超过corePoolSize时,才会有效
TimeUnit unit,//参数keepAliveTime的时间单位 TimeUnit.DAYS天,HOURS小时,MINUTES分钟,SECONDS秒,MILLISECONDS毫秒,MICROSECONDS微妙,NANOSECONDS纳秒
BlockingQueue<Runnable> workQueue, //阻塞队列,当线程数目超过核心线程数时用于保存任务的队列
ThreadFactory threadFactory, //用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程做些更有意义的事情,比如设置daemon和优先级等等
RejectedExecutionHandler handler//表示当拒绝处理任务时的策略,线程饱和策略
)
5. BlockingQueue<Runnable> workQueue 阻塞队列
用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响,一般来说,这里的阻塞队列有以下几种选择
阻塞队列类型 | 解释 |
---|---|
ArrayBlockingQueue | 基于数组的先进先出队列,有界 |
LinkedBlockingQueue | 基于链表的先进先出队列,无界 |
SynchronousQueue | 同步移交队列,无缓冲的等待队列,无界 |
PriorityBlockingQueue |
6. RejectedExecutionHandler handler 饱和策略
阻塞队列已满且线程数达到最大值时所采取的饱和策略。java默认提供了4种饱和策略的实现方式:中止、抛弃、抛弃最旧的、调用者运行。
饱和策略类型 | 解释 |
---|---|
AbortPolicy | 默认,直接抛出异常 |
CallerRunsPolicy | 只用调用者所在线程来运行任务 |
DiscardOldestPolicy | 丢弃队列里最近的一个任务,并执行当前任务 |
DiscardPolicy | 不做任何处理,直接丢弃掉 |
也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化不能处理的任务。
7. 如何合理设置线程池大小
线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。需根据压测来进行微调
最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目
线程等待时间:可以使用 System.currentTimeMillis() startTime-endTime;
线程cpu时间:可使用ThreadMxBean
private static final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
//在准备线程时先启动
threadBean.setThreadCpuTimeEnabled(true);
//返回当前线程总cpu时间,纳秒单位
System.out.println(threadBean.getCurrentThreadCpuTime());
//返回当前线程已执行的cpu时间
System.out.println(threadBean.getCurrentThreadUserTime());
参考:https://blog.csdn.net/qq_35909080/article/details/87002367