线程池 拼搏现实的明天。 2022-04-13 14:12 169阅读 0赞 ## 1.1 线程池思想概述 ## 池化技术 我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果。今天我们就来详细讲解一下Java的线程池。 ## 1.2 线程池概念 ## 程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。因为启动线程的时候会在内存中开辟一块空间,消耗系统资源,同时销毁线程的时候首先要把和线程相关东西进行销毁,还要把系统的资源还给系统。这些操作都会降低操作性能。尤其针对一个线程用完就销毁的更加降低效率。 而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,生存期较短的线程指的是用完一次线程就丢掉。更应该考虑使用线程池。 线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。 线程池工作原理如下图所示: 需求:我有一段任务,需要执行100次。 说明: 每次线程执行完任务以后,线程不会销毁,会放回线程池中,每次在执行任务的时候又会到线程池中去取线程。这样会提高效率。 合理利用线程池能够带来三个好处: 1. 降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。 2. 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。 3. 提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。 ## 1.3 线程池的使用 ## 在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池。 Java里面线程池的顶级接口是`java.util.concurrent.Executor`,但是严格意义上讲`Executor`并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是`java.util.concurrent.ExecutorService`。 ### 如何获取线程池? ### 要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此使用`java.util.concurrent.Executors`线程池工具类来生成一些常用的线程池。官方建议使用Executors工具类来创建线程池对象。 Executors是一个线程池的工具类,专门用来生产线程池。 线程池Executors的工具类中的函数如下所示,通过以下函数可以创建线程池: * `public static ExecutorService newFixedThreadPool(int nThreads)`:创建一个可重用固定线程数的线程池。 说明:以上这个函数是按照指定线程个数来创建线程池,在创建线程池的时候直接指定线程的个数。 问题:我们发现上述获取线程池之后,函数的返回值是ExecutorService ,既然是获取线程池,那么为什么返回的不是Executor线程池却是一个接口ExecutorService 呢? 进一步解释上述获取线程池的函数返回值类型ExecutorService : ExecutorService 属于真正的线程池接口。 **public interface ExecutorService extends Executor** ExecutorService 接口的父接口是Executor。 ### 如何执行我们的线程任务呢? ### 获取到了一个线程池ExecutorService 对象,那么怎么使用呢,在这里定义了一个使用线程池对象的方法如下: * void execute(Runnable command) 在将来的某个时间执行给定的命令。 说明:这个方法是ExecutorService 的父类Executor中的方法。表示获取线程池中的某一个线程对象,并执行。 使用线程池中线程对象的步骤: A:自定义一个类,作为任务类并实现Runnable接口; B:实现Runnable接口中的run方法; C:创建任务类的对象; D:获取线程池对象; E:直接执行任务; ### 用线程池执行卖票程序 ### 需求:使用线程池来完成卖票任务。 Runnable实现类代码: package com.SiyualChen.day03.test06; public class SellTicketTask implements Runnable{ private int tickets=100; @Override public void run() { while (true) { synchronized (this) { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "出票" + "这是" + (100 - tickets + 1) + "第张票"); tickets--; } else { break; } } } } } package com.SiyualChen.day03.test06; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class SellTickestDemo { public static void main(String[] args) { SellTicketTask sellTicketTask = new SellTicketTask(); ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.execute(sellTicketTask); } } } pool-1-thread-4出票这是90第张票 pool-1-thread-4出票这是91第张票 pool-1-thread-3出票这是92第张票 pool-1-thread-3出票这是93第张票 pool-1-thread-3出票这是94第张票 pool-1-thread-3出票这是95第张票 pool-1-thread-3出票这是96第张票 pool-1-thread-3出票这是97第张票 pool-1-thread-3出票这是98第张票 pool-1-thread-3出票这是99第张票 pool-1-thread-3出票这是100第张票 大家以为这样就结束啦? 有没有发现一个问题,线程是跑完了,程序没关闭。我类个去!!!这里有个坑。必须调用shutdown()函数结束线程。 shutdown()。 //结束线程 package com.SiyualChen.day03.test06; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class SellTickestDemo { public static void main(String[] args) { SellTicketTask sellTicketTask = new SellTicketTask(); ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.execute(sellTicketTask); } executorService.shutdown(); //这里是坑 } }
相关 Java 线程池、Runnable线程池、Callable线程池 线程池: 其实就是一个容纳多个线程的容器,其中的线程可以反复的使用,省去了频繁创建和销毁过程对象的操作,无需反复创建线程面消耗过多资源。 为什么要用线程池: 合理 青旅半醒/ 2023年02月26日 12:30/ 0 赞/ 50 阅读
相关 线程、线程池 创建线程的3种方法: package com.frank.threadPool.createThread; / @author 小石潭记 布满荆棘的人生/ 2022年10月22日 04:27/ 0 赞/ 384 阅读
相关 线程池 1.所谓线程池,就是程序的初始化阶段,就预先创建一批线程,每个线程都做好准备干活; 2.然后有一个任务列表,一开始为空,当有任务来了,就往任务列表里面添加;这个任务列表 痛定思痛。/ 2022年06月13日 13:22/ 0 赞/ 328 阅读
相关 线程池 西施越溪女,明艳光云海 最近用线程池和不用线程池做了个速度的测试,在这里备注下: 结果是速度不相上下; public static void main(Str 妖狐艹你老母/ 2022年05月20日 02:35/ 0 赞/ 281 阅读
相关 线程池 线程池 Java里面线程池的顶级接口是 java.util.concurrent.Executor , 但是严格意义上讲 Executor并不是一个线程池,而只是一个 迈不过友情╰/ 2022年03月06日 14:34/ 0 赞/ 400 阅读
相关 线程池 线程池 > 从字面义上来讲,是指管理一组同构工作线程的资源池。线程池是与工作队列密切相关的,其中在工作队列中(Worker Queue)保存了所有等待执行的任务。工作者( 清疚/ 2021年12月11日 03:35/ 0 赞/ 388 阅读
相关 线程池 可preStart一个或全部core thread 0,小于core则来一个任务建一个线程(firstTask),队列,额外线程,拒绝 一个AtomicInteger的 今天药忘吃喽~/ 2021年11月23日 03:40/ 0 赞/ 411 阅读
相关 线程池 1、先创建线程池 import java.util.concurrent.ArrayBlockingQueue; import java.util.concu 拼搏现实的明天。/ 2021年11月09日 14:28/ 0 赞/ 421 阅读
还没有评论,来说两句吧...