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

JAVA多线程并发编程学习笔记4——线程池,第1张

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,TFutureCallableFutureexecuteRunnablevoid
  • 处理异常

    • 使用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任务在正常完成之前被取消返回trueisDoneboolean是否已完成
  • 基本实现类是FutureTask,其同时实现了Runnable接口。所以它既可以被线程执行,又可以得到Callable的返回值。

    • 代码实现

      Callable myCom = ...;
      FutureTask task = new FutureTask(myCom);
      new Thread(task).start();
      Integer result = task.get();
      

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5481030.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-12
下一篇 2022-12-12

发表评论

登录后才能评论

评论列表(0条)

保存