栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA多线程并发编程学习笔记4——线程池

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA多线程并发编程学习笔记4——线程池

JAVA并发编程 7. 线程池 7.1 概念 7.1.1 无限制创建线程的缺点
  • 线程生命周期的开销(创建和关闭线程等开销)
  • 活动线程消耗系统资源,大量空闲线程占用更多内存,给垃圾回收器带来压力。
  • 过多的线程会影响稳定性,甚至拖垮程序。
7.1.2 简单过程和优点

过程:线程池管理一个工作者线程的同构池,并与工作队列绑定。它从工作队列中获取下一个任务并执行。

优点:

  • 可以重用线程,减少创建和关闭线程的开销。

  • 提高响应性,不需要创建线程也就不会延迟任务的执行。

  • 通过调整线程池大小,可以保持处理器忙碌的同时防止过多线程竞争资源(耗尽内存)。

7.1.3 线程池的大小
  • 对于计算密集型任务,线程数为CPU+1。

  • 包含I/O等阻塞操作可以加大线程池。

  • 计算公式:No(threads) = No(CPU)*U(cpu)*(1+W/C)

    No表示数量,U表述利用率,W/C为等待时间域计算时间的比率

7.1.4 线程池死锁
  • 线程池中一个任务依赖于其他任务的执行,就可能产生死锁。
  • 解决:给同一线程池提交相互独立的任务,而不是彼此依赖的任务。
7.2 Executor框架 7.2.1 作用
  • 支持不同类型的任务执行策略
  • 为任务提交和任务执行之间的解耦提供了标准方法
  • 提供对生命周期的支持以及钩子函数
  • 可以添加统计收集、应用程序管理机制和监视器等扩展
  • 基于生产者-消费者模式
7.2.2 Executor接口
  • 唯一方法

    方法名返回值描述
    execute(Runnable)void在将来的某个时间执行给定的命令
7.2.3 ExecutorService接口
  • 继承Executor接口,添加了用于生命周期管理的方法

  • 提供了三种生命周期状态:运行、关闭、终止

  • 部分方法

    方法名返回值描述
    submit(Runnable)Future提交一个可运行的任务执行,并返回一个表示该任务的未来。
    shutDown()void平缓关闭:停止接受新任务,等待已提交任务完成
    shutDownNow()List强制关闭:尝试取消所有任务,返回等待的任务列表
    isShutDown()boolean判断是否关闭
    isTerminated()boolean所有任务完成会进入终止状态
    awaitTermination(long, TimeUnit)boolean等待进入终止状态,返回一段时间后是否关闭。通常后接shutdown
  • 实现类:ThreadPoolExecutor

7.2.4 ScheduledExecutorService接口
  • 继承ExecutorService接口

  • 作用:调度命令在给定的时间后或定期执行

  • Timer:Timer只创建唯一的线程执行所有任务,耗时的任务会影响其他任务的时效性。且不捕获异常。

  • 部分方法

    方法名描述
    schedule(Runnable, long, TimeUnit)在一段时间后执行任务
    scheduleAtFixedRate(Runnable, long, long, TimeUnit)在一段时间后执行并周期执行
    scheduleWithFixedDelay(Runnable, long, long, TimeUnit)在一段时间后执行,并按任务结束后固定时间执行
  • 实现类:ScheduledThreadPoolExecutor

7.2.5 ThreadPoolExecutor类
  • 继承AbstractExecutorService,间接实现ExecutorService接口

  • 构造方法的参数

    参数类型描述
    corePoolSizeint核心池大小,工作队列满前的大小
    maxPoolSizeint最大池大小,可同时活动线程数上限
    keepAliveTimelong存活时间,
    unitTimeUnit超过核心池大小的空闲线程被销毁的时间
    workQueueBlockingQueue工作队列,决定了排队方法
    threadFactoryThreadFactory(可选)线程工厂,用于创建线程
    handlerRejectedExecutionHandler(可选)拒绝策略,
  • 工作队列

    • 当线程池线程大于核心线程数,且工作队列未满时,任务会加入工作队列
    队列描述
    SynchronousQueue同步提交队列,没有容量,新任务来时直接创建新线程或执行拒绝策略
    ArrayBlockingQueue有限队列,可指定容量,队列满后可创建新的线程执行队头的任务
    linkedBlockingQueue无限队列,任何任务都可以加入
    PriorityBlockingQueue优先级队列,也是无限
  • 线程工厂

    • 线程池需要创建线程,通过线程工厂类的newThread()创建一个新的、非守护线程。
    • 重写ThreadFacroty类的newThread()方法自定义线程工厂
  • 拒绝策略(饱和策略)

    • 池中线程数达到最大数量,会执行拒绝策略。
    策略描述
    AbortPolicy默认策略,抛出异常
    CallerRunsPolicy调用者运行,不会丢弃也不会抛异常,在调用者线程执行新任务
    DiscardOldestPolicy遗弃最旧,将最老的任务丢弃,提交新任务
    DiscardPolicy遗弃,放弃任务
    • 可以重写RejectedExecutionHandler类的rejectedExecution()方法自定义拒绝策略。
  • 代码实现

    int corePoolSize = 1;
    int maxPoolSize = 1;
    long keepAliveTime = 0L;
    int capacity = 10;
    ThreadPoolExecutor executor = 
        new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime,
                               TimeUnit.MILLISECONDS,
                              new ArrayBlockingQueue(capacity),
                              new ThreadPoolExecutor.DiscardPolicy());
    
  • 构造后再定制属性

    方法描述
    setCorePoolSize(int)设置核心池大小
    setMaximumPoolSize(int)设置最大池大小
    setKeepAliveTime(long, TimeUnit)设置存活时间
    setThreadFactory(ThreadFactory)设置线程工厂
    setRejectedeExecutionHandler(RejectedExecutionHandler)设置拒绝策略
  • 监控线程池

    方法返回值描述
    getCorePoolSize()int核心池大小
    getMaximumPoolSize()int最大池大小
    getPoolSize()int当前池大小
    getLargestPoolSize()int历史最大池大小
    getQueue()BlockingQueue工作队列
    getActiveCount()int当前活动线程数
    getCompletedTaskCount()long完成任务数
    getTaskCountlong收到的任务总数
    getKeepAliveCountlong存活时间
  • 扩展线程池

    方法描述
    afterExecute(Runnable, Throwable)任务结束后会调用
    beforeExecute(Runnable, Throwable)任务执行前会调用
    terminated()线程池完成关闭动作后调用
7.2.6 Executors
  • 通过静态工厂方法提供预设配置的线程池

  • 创建线程方法(返回类型是ExecutorService或ScheduledExecutorService)

    方法描述
    newCachedThreadPool()可缓存的线程池,可灵活回收空闲线程或添加新线程
    newFixedThreadPool(int)定长线程池,每提交一个任务就创建一个线程,直到达到最大池大小
    newSingleThreadExecutor()单线程,只创建一个线程
    newScheduledThreadPoll(int)定长周期线程池
7.2.7 submit()与execute()
  • 接受参数和返回值不同

    参数返回值参数返回值参数返回值
    submitRunnableFutureRunnable,TFutureCallableFuture
    executeRunnablevoid
  • 处理异常

    • 使用submit()提交的任务不会抛出异常,除非使用Future的get()方法
    • execute()会抛出异常。
7.3 有结果的任务 7.3.1 Callable
  • Callable与Runnable相似,但是有返回值

  • 只有一个方法call(),返回值为类型参数。

    public interface Callable{
        V call() throws Exception;
    }
    
7.3.2 Future
  • 用来保存异步计算的结果

  • 接口方法

    方法返回值描述
    get()V等待计算完成,然后返回结果。被中断会抛中断异常
    get(long, TimeUnit)V在指定时间内完成并返回结果,否则抛出超时异常
    cancel(boolean)void若未开始计算则取消;已经开始计算,可能被中断
    isCancelled()boolean任务在正常完成之前被取消返回true
    isDoneboolean是否已完成
  • 基本实现类是FutureTask,其同时实现了Runnable接口。所以它既可以被线程执行,又可以得到Callable的返回值。

    • 代码实现

      Callable myCom = ...;
      FutureTask task = new FutureTask(myCom);
      new Thread(task).start();
      Integer result = task.get();
      
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/488899.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号