专业模板建站价格,广东seo课程,网页无法访问 wordpress,吉林省舒兰市建设银行网站概述
在处理大量任务时,重复利用线程可以提高程序执行效率,因此线程池应运而生。
它是一种重用线程的机制,可以有效降低内存资源消耗提高响应速度。当任务到达时#xff0c;任务可以不需要的等到线程创建就能立即执行线程池可以帮助我们更好地管理线程的生命周期和资源使用,…概述
在处理大量任务时,重复利用线程可以提高程序执行效率,因此线程池应运而生。
它是一种重用线程的机制,可以有效降低内存资源消耗提高响应速度。当任务到达时任务可以不需要的等到线程创建就能立即执行线程池可以帮助我们更好地管理线程的生命周期和资源使用,避免线程频繁地创建和销毁带来的性能问题
同时,线程池还可以提供一些额外的功能,例如线程池的大小控制、线程池的任务队列、线程池的拒绝策略等。线程池中通常维护一个线程队列,线程队列中保存着已创建的线程,当有新的任务需要执行时,线程池中的线程就可以从队列中取出一个线程来执行任务,任务执行完毕后线程可以被放回线程队列中,等待下一个任务的到来 核心执行流程 线程池执行流程 当有新任务需要线程执行时,线程池会先判断是否有空闲的核心线程,如果有则将任务分配给其中一个空闲的核心线程执行。如果没有空闲的核心线程或者核心线程的数量还没达到最大值则创建一个新的核心线程来执行任务若核心线程已经达到最大值且工作队列未满,则将新提交的任务存储在这个工作队列中。如果工作队列已满,则会判断线程池中的线程数是否已经达到最大值,如果没有则创建一个新的非核心线程来执行任务若工作队列已满且线程池中的线程都已经处于工作状态,即核心线程和非核心线程都在执行任务,则交给饱和策略来处理这个任务。饱和策略可以决定如何处理无法处理的任务,例如抛出异常或者阻塞任务提交 线程池状态 RUNNING该状态代表能接受新任务以及处理任务(初始状态)SHUTDOWN该状态代表不接受新任务,但处理已添加的任务(调用shutdown()时,由RUNNING-SHUTDOWN)STOP该状态时表示不接受新任务,不处理已添加任务,并会中断正在处理中的任务(调用shutdownNow()时,由RUNNING或者SHUTDOWN→STOP)TIDYING进入SHUTDOWN或者STOP状态后,所有任务都被处理或者清理干净后就会进入该状态,同时会执行terminated()方法该方法是个钩子函数,自定义实现TERMINATED结束状态,执行完terminated方法后由TIDYING-TERMINATED Executor 框架
两级调度模型 在HotSpotVM的线程模型中,Java线程(java.lang.Thread)被一对一映射为本地操作系统线程 Java线程启动时会创建一个本地操作系统线程当该 Java 线程终止时这个操作系统线程也会被回收。操作系统会调度所有线程并将它们分配给可用的CPU
在上层架构中,Java多线程程序通常把应用分解为若干个任务,应用程序通过Executor框架将这些任务映射为固定数量的线程在下层架构中,操作系统内核将这些线程映射到硬件处理器上,下层的调度不受应用程序的控制
Executor结构 Executor框架包含的主要的类与接口如图所示
Executor是一个接口,它是Executor框架的基础,它将任务的提交与任务的执行分离开来ThreadPoolExecutor是线程池的核心实现类,用来执行被提交的任务ScheduledThreadPoolExecutor是一个实现类,用来延迟之后执行任务或者定时执行任务。ScheduledThreadPoolExecutor比Timer更灵活,功能更强大实现Future接口的FutureTask类,代表异步计算的结果Runnable接口和Callable接口的实现类,都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行
ThreadPoolExecutor
构造函数详细说明
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueRunnable workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize 0 ||maximumPoolSize 0 ||maximumPoolSize corePoolSize ||keepAliveTime 0)throw new IllegalArgumentException();if (workQueue null || threadFactory null || handler null)throw new NullPointerException();this.acc System.getSecurityManager() null ?null :AccessController.getContext();this.corePoolSize corePoolSize;this.maximumPoolSize maximumPoolSize;this.workQueue workQueue;this.keepAliveTime unit.toNanos(keepAliveTime);this.threadFactory threadFactory;this.handler handler;
}
参数介绍:
corePoolSize:核心线程池个大小。一般来说任务比较耗时可以配CPU核数*2,因为这样可以充分利用CPU,任务小并且执行很快则可以配CPU核数1或者更小(因为线程上下文切换耗时)获取CPU核心数Runtime.getRuntime().availableProcessors()maximumPoolSize最大线程池大小。当线程数corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务,总线程数≤maximumPoolSizekeepAliveTime空闲时间,超过核心线程数的线程在到达空闲时间后会被销毁TimeUnit : 时间单位BlockingQueue用来暂时保存任务的队列阻塞队列ThreadFactory自定义的线程工厂,默认是一个新的、非守护线程并且不包含特殊的配置信息,我们也可以自定义加入我们的调试信息,比如线程名称、错误日志等RejectedExecutionHandler饱和策略。当线程数maximumPoolSize,且任务队列已满时,多余的任务需要采取的措施,有以下几种默认AbortPolicy AbortPolicy丢弃任务并抛出RejectedExecutionException异常DiscardPolicy: 丢掉这个任务并且不会有任何异常DiscardOldestPolicy丢弃最老的。也就是说如果队列满了会将最早进入队列的任务删掉腾出空间再尝试加入队列CallerRunsPolicy主线程会自己去执行该任务不会等待线程池中的线程去执行自定义:当然也可以自定义策略
常用ThreadPoolExecutor类型
ThreadPoolExecutor通常使用工厂类Executors来创建,包括3种ThreadPoolExecutor类型
FixedThreadPool可重用固定线程数的线程池SingleThreadExecutor单个线程的线程池只有一个工作线程CachedThreadPool根据需要创建新线程的线程池
FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable());
}
其中corePool和maximumPoolSize 都被设置成指定的参数keepAliveTime设置为0L,意味着多余的空闲线程会被立即终止适用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景,更适合于负载比较重的服务器 fixedThreadPool执行流程 如果当前线程少于corePool,则创建新线程来执行当前任务当运行的线程数等于corePool之后,将任务加入LinkedBlockingQueue队列中线程执行完当前任务后会循环反复从LinkedBlockingQueue获取任务来执行
由于为LinkedBlockingQueue无界队列(长度Integer.MAX_VALUE),所以会出现如下情景
maximumPoolSize和keepAliveTime参数将会无效,因为maximumPoolSizecorePool不会拒绝任务,因为是无界队列,任务不会满
SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable()));
}
corePool和maximumPoolSize 均被设置成了1,其他影响和运行方式都与FixedThreadPool相同
CachedThreadPool
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueueRunnable());
}
corePoolSize核心线程数为0而maximumPoolSize为Integer.MAX_VALUE(21亿多),意味着没有空闲线程就会不断的创建线程去执行,极端情况会耗尽CPU和内存资源;keepAliveTime60s后空闲线程会被终止,所以长时间内保持空闲的情况下不会占用任何资源SynchronousQueue是没有容量的阻塞队列,每个插入操作都会等待另一个线程对应的取出操作适用于执行很多的短期异步任务的小程序或者是负载较轻的服务器
ScheduleThreadPoolExecutor
构造函数
public ScheduledThreadPoolExecutor(int corePoolSize,RejectedExecutionHandler handler) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), handler);
} ScheduledThreadPoolExecutor为了实现周期性任务对ThreadPoolExecutor做了如下修改
使用DelayedWorkQueue作为任务队列获取任务的方式不同同样都是队列的take但增加了时间的判断执行周期任务后增加了额外的处理需要把任务重新添加进队列
常用ScheduleThreadPoolExecutor类型
ScheduledThreadPoolExecutor通常使用工厂类Executors来创建,2种类型
ScheduledThreadPoolExecutor: 包含若干个线程 ScheduledThreadPoolExecutor public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) ScheduledThreadPoolExecutor 适用于需要多个后台线程执行周期任务同时为了满足资源管理的需求而需要限制后台线程的数量的应用场景 SingleThreadScheduledExecutor: 只包含一个线程 ScheduledThreadPoolExecutor public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) SingleThreadScheduledExecutor 适用于需要单个后台线程执行周期任务同时需要保证顺序地执行各个任务的应用场景
FutureTask
Future接口和实现Future接口的FutureTask类用来表示异步计算的结果。当我们把Runnable接口或Callable接口的实现类提交(submit)给 ThreadPoolExecutor或ScheduledThreadPoolExecutor时,ThreadPoolExecutor或ScheduledThreadPoolExecutor会向我们返回一个FutureTask对象 Executor 实践
ThreadPoolExecutor
package com.bierce;
import java.util.concurrent.*;
public class TestThreadPoolExecutor {public static void main(String[] args) throws ExecutionException, InterruptedException {//创建线程池ExecutorService executorService Executors.newFixedThreadPool(5);//方式一Runnable方式的分配10个任务提交给线程池ThreadPoolDemo threadPoolDemo new ThreadPoolDemo();for (int i 0; i 10; i) {executorService.submit(threadPoolDemo);}//方式二Callable方式的分配10个任务提交给线程池for (int i 0; i 10; i) {FutureObject sum executorService.submit(() - {int sum1 0;for (int i1 1; i1 100; i1) {sum1 i1;}return sum1;});System.out.println(Thread.currentThread().getName() : sum.get()); //main:5050}//关闭线程池executorService.shutdown();}
}
class ThreadPoolDemo implements Runnable{private int i 0;Overridepublic void run() {while (i10){System.out.println(Thread.currentThread().getName() : i);}}
}
ScheduleThreadPoolExecutor
package com.bierce;
import java.util.Random;
import java.util.concurrent.*;
public class TestScheduleThreadPool {public static void main(String[] args) throws ExecutionException, InterruptedException {ScheduledExecutorService scheduledExecutorService Executors.newScheduledThreadPool(5);for (int i 1; i 5 ; i) {//调用schedule方法执行任务FutureInteger random scheduledExecutorService.schedule(new CallableInteger() {Overridepublic Integer call() throws Exception {int random new Random().nextInt(100);System.out.println(Thread.currentThread().getName() : random);return random;}},1,TimeUnit.SECONDS); //每隔一秒执行一个任务System.out.println(random.get());}scheduledExecutorService.shutdown(); //关闭线程池}
}