做农业种子的网站,中国十大龙头企业排名,江苏建设人才的网站,公司logo素材线程模型线程模型分为两类#xff0c;用户级线程(ULT)和内核级线程(KLT)用户级线程(ULT)#xff1a;user level threads#xff0c;系统内核对ULT无感知#xff0c;线程的创建和调度都由用户级APP进程管理#xff1b;即APP自行管理的线程#xff0c;就是用户级线程内核级…线程模型线程模型分为两类用户级线程(ULT)和内核级线程(KLT)用户级线程(ULT)user level threads系统内核对ULT无感知线程的创建和调度都由用户级APP进程管理即APP自行管理的线程就是用户级线程内核级线程(KLT)kernel level threads线程的创建调度和切换上下文等都由操作系统内核管理如图所示ULT模型中每个进程创建的线程均由自身进程维护管理而KLT模型中进程创建的线程由系统内核进行维护管理。在执行的区别之上ULT和KLT最大的区别就是ULT线程的调度不需要内核直接参与控制简单创建和销毁线程、线程切换代价等线程管理的开销比内核线程少得多。但是其资源调度按照进程进行不能利用系统的多核处理多个处理器下同一个进程中的线程只能在同一个处理器下分时复用KLT由内核进行调度当有多个处理器时一个进程的多个线程可以同时执行但是KLT线程的创建和切换等开销很大。Java线程是依赖于系统内核通过JVM调用系统库创建内核线程。Java的Thread和内核线程呈 1:1映射关系。by the way这也是为什么我们需要线程池进行线程池化管理的原因。线程池基础概念线程是程序运行的载体说白了就是拥有cpu多长时间的执行权。而由于java线程是内核级线程带来的昂贵开销成本在平时运用场景中我们也经常使用线程池对线程进行池化管理。线程池能为我们带来3大好处复用已创建的线程降低创建销毁线程等带来的资源消耗提高响应速度。线程早已创建好不需要在等待线程创建就可以直接使用可管理线程。由于线程是稀有资源不能无限创建因此用线程池能对线程进行统一规划监控和分配在线程池中有几项概念最为重要核心线程数最大线程数等待队列饱和策略。它们的执行过程如下图。为加强记忆可以用工厂干活的方式理解。把核心线程数看作是正式工当来了一堆任务的时候正式工陆续开始干活当任务增多的时候正式工们手头上的任务还没干完于是先放阻塞队列等待待会儿处理后来任务量暴涨阻塞队列也满了于是就请一些临时工来干活于是正式工数临时工数 最大线程数再后来线程数持续增长最大线程数也满了只能做一些饱和策略限制任务的提交了。线程池的使用我们可以通过new ThreadPoolExecutor的方式创建线程池。//构造方法public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue)public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory)public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,RejectedExecutionHandler handler)public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)其中的参数需要说明下corePoolSize核心线程数。线程池在最初阶段池中线程数为0当接收到一个任务后就创建一个线程。即使之前的线程执行完毕空闲新任务提交过来依然会创建线程。直到创建线程到核心线程数。如果调用了prestartAllCoreThreads方法那么线程池会预先创建好线程。BlockingQueue: ⽤于保存等待执⾏的任务的阻塞队列可参考JUC的7种阻塞队列这里不再赘述maximumPoolSize线程池允许创建的最⼤线程数。如果队列满了并且已创建的线程数⼩于最⼤线程数则线程池会再创建新的线程执⾏任务TimeUnit线程活动保持时间的单位keepAliveTime线程活动保持时间。当线程池中创建的线程数量超过核心线程数且有线程空闲超过该时间空闲线程将会被回收至核心线程数大小。当设置为0即只要线程空闲就立即回收ThreadFactory⽤于设置创建线程的⼯⼚可以通过线程⼯⼚给每个创建出来的线程设置更有意义的名字。附录附上线程工厂的用法例子。RejectedExecutionHandler(饱和策略)当队列和线程池都满了说明线程池处于饱和状态那么必须采取⼀种策略处理提交的新任务。这个策略默认情况下是AbortPolicy。在JDK1.5中Java线程池框架提供了以下4种策略。AbortPolicy直接抛出异常。CallerRunsPolicy当任务添加到线程池中被拒绝时会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。DiscardOldestPolicy线程池会放弃等待队列中最旧的未处理任务然后将被拒绝的任务添加到等待队列中。DiscardPolicy不处理丢弃掉。当然也可以自定义在附录举了一个demo可参考。举上一个较为完整的线程池创建示例BlockingQueue workQueue new ArrayBlockingQueue(5);ThreadPoolExecutor threadPoolExecutor new ThreadPoolExecutor(5, 10, 1000, TimeUnit.MILLISECONDS, workQueue, new ThreadPoolExecutor.AbortPolicy());线程池的工作状态线程池共有5种生命状态RUNNINGSHUTDOWNSTOPTIDYINGTERMINATEDRUNNING接受新任务并处理排队的任务SHUTDOWN不接受新任务但处理排队的任务STOP不接受新任务不处理排队的任务中断正在进行的任务TIDYING所有任务都已终止workerCount为零将运行terminate()钩子方法TERMINATED线程池终止线程池提交任务的方式有两种分别为execute()和 submit()⽅法。execute()⽅法⽤于提交不需要返回值的任务⽆法判断任务是否被线程池执⾏成功。submit()⽅法⽤于提交需要返回值的任务。线程池会返回⼀个future类型的对象可通过future对象判断线程是否执行成功获取返回值等。线程池关闭的方式也有两种shutdown()和shutdownNow()⽅法可关闭线程池。它们的原理是遍历线程池中的⼯作线程然后逐个调⽤线程的interrupt⽅法来中断线程所以⽆法响应中断的任务可能永远⽆法终⽌。区别在于shutdownNow 更改状态成STOP然后尝试停⽌所有的正在执⾏或暂停任务的线程并返回等待执⾏任务的列表⽽shutdown更改状态成SHUTDOWN状态然后中断所有没有正在执⾏任务的线程正在执行的线程会继续执行完毕。附1.线程池设置多少合适2. 线程工厂的demo/*** 实现线程工厂的接口然后实现自定义内容。重写newThread方法*/public class MyThreadFactory implements ThreadFactory {private static int COUNTER 0;private static String THREAD_PREFIX myThread;Overridepublic Thread newThread(Runnable r) {int i COUNTER;return new Thread(r, THREAD_PREFIX i);}//使用public static void main(String[] args) {MyThreadFactory myThreadFactory new MyThreadFactory();Thread thread myThreadFactory.newThread(new Runnable() {Overridepublic void run() {}});thread.start();}}2. 自定义饱和策略//需要实现RejectedExecutionHandler重写rejectedExecution方法class MyRejected implements RejectedExecutionHandler {public MyRejected() {}Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {System.out.println(现线程池中的情况为 executor.getActiveCount());System.out.println(当前被拒绝任务为 r.toString());}}