怎么查看网站是哪个公司建的,环保油 东莞网站建设,杭州工程招标网,seo运营是做什么的#x1f490;个人主页#xff1a;初晴~
#x1f4da;相关专栏#xff1a;多线程 / javaEE初阶 还记得我们一开始引入线程的概念#xff0c;就是因为进程太“重”了#xff0c;频繁创建销毁进程的开销是非常大的。而随着计算机的发展#xff0c;业务上对性能的要求越来越…
个人主页初晴~
相关专栏多线程 / javaEE初阶 还记得我们一开始引入线程的概念就是因为进程太“重”了频繁创建销毁进程的开销是非常大的。而随着计算机的发展业务上对性能的要求越来越高导致线程的创建/销毁频次也越来越高频繁创建/销毁线程的开销也会非常大了会开始明显影响性能了。为了缓解这一问题就发展出了“线程池”这一结构。那么线程池具体是如何实现的又该如何应用呢就让博主带大家好好梳理一下吧。
一、何为线程池 让我们先来看一下这个场景 肯德基要实现外卖业务“宅急送”可以有两种实现方式 第一种方式每次收到一个顾客的订单就临时聘用一个配送员完成这单外卖的配送配送完成之后就当场解雇这个配送员并结算工资。 第二种方式提前聘用几个配送员每收到一个顾客的订单就将其分配给一名空闲的配送员去完成配送在配送完成后并不会直接解雇而是会等待其它订单继续配送。当实在发现没有订单时才把这几个配送员解雇了 由于聘用和解雇配送员的操作都比较繁琐像第一种方法就会频繁执行这两个操作效率很低。而方法二则提前雇用好了几个配送员且中途配送需求都交给他们来处理极大地减少了雇用和解雇操作的次数明显提高了效率。
线程池亦是如此它预先创建了一组可重用的线程当有新的任务提交给线程池时线程池就会从池中取出一个空闲的线程来执行这个任务而当线程完成任务后它并不会被销毁而是再次返回到线程池中等待下一个任务。从而大幅提高线程利用率提升效率。 优点 资源重用避免频繁创建和销毁线程带来的开销因为创建和销毁线程是比较耗时的操作。提高响应速度当任务到达时线程池可以快速分配已有线程进行处理而不需要等待新线程的创建。控制资源消耗通过限制最大线程数量来控制资源的消耗防止过多的线程同时运行而导致系统资源枯竭。有效控制线程生命周期线程池可以对线程进行统一管理包括线程的创建、分配、回收等。简化线程管理线程池提供了一种机制使得线程管理变得更加简单和高效。 二、标准库中的线程池
在Java中线程池是由java.util.concurrent包下的几个类来实现的主要包括 Executor这是最基础的接口定义了执行任务的方法。ExecutorService扩展了Executor接口提供了更多的管理方法如启动、关闭线程池等。ThreadPoolExecutor实现了ExecutorService接口提供了更详细的线程池配置和管理方法。Executors这是一个工具类提供了创建不同类型的线程池的工厂方法。 我们接下来就先来介绍一下ThreadPoolExecutor类的构造方法吧 参数含义 int corePoolSize 核心线程数int maximumPoolSize 最大线程数即核心线程数与非核心线程数之和long keepAliveTime 非核心线程在线程空闲时最大存活时间超过这个时间就会被销毁TimeUnit unit 最大存活时间的单位秒分钟小时天……BlockingQueueRunnable workQueue 工作队列使用者通过类似“submit”的等待把要执行的任务设定到线程池内让线程池内部的工作线程负责执行这些任务ThreadFactory threadFactory 线程工厂就是Thread 类的工厂类通过这个类完成Thread类的实例创建和初始化操作。可以针对线程池中的线程进行批量的设置属性RejectedExecutionHandler handler 拒绝策略如果线程池队列满了依然继续往队列中添加任务不要阻塞而是通过各种拒绝策略来处理。 java标准库给出了四种拒绝策略 但是由以上介绍我们可以看出虽然ThreadPoolExecutor类的功能很强大但使用很麻烦。为了使用更加便利标准库又对这个类进行了封装让Executors类提供了一些工厂方法可以更方便地构造出线程池。一些工厂方法简介 简单应用
public class Main {public static void main(String[] args) {ExecutorService service Executors.newFixedThreadPool(4);for(int i0;i100;i){int idi;service.submit(()-{Thread currentThread.currentThread();System.out.println(hello world id,current.getName());});}}
} 但是我们发现这个代码执行后虽然100个任务都执行完毕了但是整个进程却没有结束这时为什么呢因为线程池创建出来的线程默认是“前台线程”即使 main 线程结束了线程池里的前台线程也会仍然存在导致进程并不会结束。
我们可以利用“shutdown方法”来强制终止线程池中的所有线程 这回进程就能正常结束了 注意 在使用线程池时需要指定线程个数这个值并没有统一的规范最好通过“实验”的方法给线程池设置不同数再分别进行性能测试然后分析响应时间/消耗资源等指标来挑选一个合适的值这样才是最好的 三、线程池的实现
我们这里就试着实现一下简单的固定线程数目的线程吧。
class MyThreadPool{private BlockingQueueRunnable queuenew ArrayBlockingQueue(1000);private volatile Boolean isAlivetrue;public MyThreadPool(int n){for(int i0;in;i){Thread tnew Thread(()-{while(isAlive){try {Runnable runnablequeue.take();runnable.run();} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();}}//添加任务public void submit(Runnable runnable){try {queue.put(runnable);} catch (InterruptedException e) {throw new RuntimeException(e);}}public void shutdown(){isAlivefalse;}
}
public class Main {public static void main(String[] args) throws InterruptedException {MyThreadPool myThreadPoolnew MyThreadPool(4);for (int i 0; i 100; i) {int idi;myThreadPool.submit(()-{System.out.println(执行任务id, Thread.currentThread().getName());});}Thread.sleep(1000);myThreadPool.shutdown();}
} 那么本篇文章就到此为止了如果觉得这篇文章对你有帮助的话可以点一下关注和点赞来支持作者哦。作者还是一个萌新如果有什么讲的不对的地方欢迎在评论区指出希望能够和你们一起进步✊