JVAV线程基础,线程池

线程池

​ 线程池是一种池化思想管理线程的工具 是创建管理线程的地方 , 当我们的每次使用线程的时候都要创建 销毁 会消费消耗系统很大资源, 为了避免这种情况可以使用线程池 来进行线程的重用 同时也可以 提高响应速度 当任务来临时 不用等待线程的创建了

 

线程池会初始化一些线程放在池子里 当需要线程的时候去线程池里取 取出来之后将线程标记为占用状态 当线

使用完毕 线程不是销毁而是回收到池子中 并标记为空闲状态 当线程池的线程都被占用 别的程序需要线程的时

候 只能阻塞等待 等待别的线程池中有空闲的线程 再来使用;

 

创建 需要开辟虚拟机栈,本地方法栈、程序计数器等线程私有的内存空间。

线程使应用能够更加充分合理的协调利用cpu 、内存、网络、i/o等系统资源。

 

线程池执行流程

 

 

线程的执行流程

 

 

 

创建线程的几种方式

1. new Thread()    Thread是一个类实现了Runnable()接口,
2. new Runnable() Runnable()是一个接口,里面一个抽象方法 run();
3. Callable<T>() (返回一个参数,需传返回值类型)   Callable<T>()接口使用了泛型,里面一个call()方法
4. 使用线程池

线程池创建方式

两种创建方式 :Executors.  和 new ThreadPoolExecutor()

Executors 内部四种创建线程池的方式

newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

 

newCachedThreadPool



public static ExecutorService newCachedThreadPool() {
  return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                60L, TimeUnit.SECONDS,
                                new SynchronousQueue<Runnable>());
}


// newCachedThreadPool() 带有缓存时间的线程池 核心线程数为0,最大线程数为Integer.Max_Value,线程存活时间为60S,阻塞队列为SynchrosQueue
// 这个线程池可以无限创建线程,但是线程使用完会有60s的存活时间,等待别的任务来使用这个空闲线程,如果没有任务来使用,则被回收,
// SynchronousQueue阻塞队列,他是将任务直接交给线程而不保存他们,当所有的线程都在工作(没有空闲线程时),任务会尝试加入队列失败,直接创建新的线程加入线城池。

newScheduledThreadPool

public ScheduledThreadPoolExecutor(int corePoolSize) {
  super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
        new DelayedWorkQueue());
}

// newScheduledThreadPool() 定时执行线程,可以做定时任务, 核心线程数自定义,最大线程数为Integer.Max_Value,存活时间为0秒, DelayedWorkQueue 实现延迟获取的无界队列
// 定时执行固定的线程

newFixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads) {
  return new ThreadPoolExecutor(nThreads, nThreads,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>());
}
//newFixedThreadPool() 固定线程池,核心线程池数等于最大线程数,存活时间为0,阻塞队列为无界阻塞队列 LinkedBlockingQueue
// 同时只能运行固定的线程,多余的任务进入阻塞队列等待,线程空余然后执行

newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
  return new FinalizableDelegatedExecutorService
      (new ThreadPoolExecutor(1, 1,
                              0L, TimeUnit.MILLISECONDS,
                              new LinkedBlockingQueue<Runnable>()));
}
// newSingleThreadExecutor() 只会用唯一的线程执行工作,核心线程和最大线程都为1,存活时间为0,使用无界阻塞队列LinkedBlockingQueue,遵循FIFO,后进LIFO

为什么不推荐使用Executors 而是推荐使用ThreadPoolExecutor


1.Executors 创建线程不够灵活,线程池的参数都是定死的,不能根据业务进行具体参数的改变

2.newCachedThreadPool() 和 newScheduledThreadPool() 最大线程数数为Integer.MAX_VALUE,有个可能创建大量的线程,造成OOM

3.newFixedThreadPool() 和 newSingleThreadExecutor() 使用阻塞队列最大为Integer.MAX_VALUE,有可能堆积大量的请求在队列中,造成OOM

4.使用 ThreadPoolExecutor()创建线程,各个参数都根据业务需求自定义,相对比较灵活 , 这样可以避免造成资源浪费

Integer.MIX_VALUE 和 Integer.MAX_VALUE   - 2 147 483 647 ~ 2 147 483 647

 

队列

队列有界性数据结构
ArrayBlockingQueue bounded(有界) 加锁 arrayList
LinkedBlockingQueue optionally-bounded 加锁 linkedList
PriorityBlockingQueue unbounded 加锁 heap
DelayQueue unbounded 加锁 heap
SynchronousQueue bounded 加锁
LinkedTransferQueue unbounded 加锁 heap
LinkedBlockingDeque unbounded 无锁 heap

ArrayBlockingQueue : 有界阻塞队列,底层是数组实现,遵循FIFO,持有公平锁和非公平所

LinkedBlockingQueue : 有界阻塞队列,底层是链表实现,遵循FIFO, 最大值是Integer.MAX_VALUE

SynchronousQueue : 无缓冲阻塞队列,一个不储存元素的阻塞队列,会直接将任务交给消费者

DelayQueue : 实现了BlockingQueue接口,继承了Delayed,内部使用了Leaded/followers模式

可以用来做定时任务,延迟任务。

posted @ 2021-03-07 18:10  爵士灬  阅读(118)  评论(0编辑  收藏  举报