合肥网络公司 网站建设,博客网站开发,男生和男生男生做的漫画网站,参考文献网站开发目录 前言#xff1a;
1.什么是线程池
2.标准库中的线程池
3.实现线程池
结束语#xff1a; 前言#xff1a;
在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下#xff0c;那么这节中小编将分享一下多线程中的线程池。给大家讲解一…目录 前言
1.什么是线程池
2.标准库中的线程池
3.实现线程池
结束语 前言
在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下那么这节中小编将分享一下多线程中的线程池。给大家讲解一下什么是“池”为什么要使用线程池。
1.什么是线程池
之前我们也有讲过“池”这个概念我们讲过字符串常量池数据连接池...
线程池就是提前把线程准备好创建线程不是直接从系统中申请而是从池子中拿当线程不用了的时候也是还给池子。它存在的目的就是为了提高效率它最大的好处就是减少每次启动、销毁线程的损耗。线程的创建虽然比进程轻量但是在频繁的创建的情况下开销也是不可忽略的。
那么为什么从池子里拿比创建线程要更高效呢
从线程池拿线程纯粹的用户态操作。从系统创建线程涉及到用户态和内核态之间的切换。真正的创建是要在内核态完成。
在上述过程中提到了用户态、内核态这两个概念那么下来给大家解释一下什么是用户态什么是内核态。 一个操作系统 内核 配套的应用程序 其中内核就是操作系统中最核心的功能模块的集合里面有硬件管理、各种驱动、进程管理、内存管理、文件系统...内核则需要给上层的应用程序提供支持。
比如我们执行println(hello)这样的一个操作。
首先应用程序调用系统内核告诉内核我要进行打印一个字符串的操作内核再通过驱动程序操作显示器来完成上述的请求。应用程序有很多但是内核只有一个内核要给这么多程序提供服务有的时候服务就不会那么及时。
举一个例子比如银行里的工作人员和来银行办理事务的人假设工作人员只有一个人客户有很多此时工作人员就相当于内核客户就是用户。工作人员待的柜台就是用户态银行的大厅就是用户态。如下图所示 滑稽A此时来到柜台给工作人员说我想办张银行卡。
此时就需要复印一些文件这时我们有两种解决办法
A滑稽自己去大厅的复印机去复印然后拿给工作人员。工作人员去柜台里面的复印机去复印。
那么此时如果A滑稽自己去复印的话速度就会很快立即复印立即回来。但是如果是工作人员去复印的话可能就会很慢因为柜台只有它一个人他可能还需要给其他人提供服务。所以这也就例比于我们计算机中的用户态操作和内核态操作了A滑稽自己复印就是用户态操作而工作人员复印就是内核态操作。
结论纯用户态操作时间是可控的。涉及到内核态操作时间就不太可控了。
2.标准库中的线程池
Java标准库中提供了线程的线程池。
ExecutorService pool Executors.newFixedThreadPool(10); 在这里我们可以看到和我们之前创建一个对象不太一样。 注意这里我们使用的是工厂模式
创建对象的时候不再直接new而是使用一些其他方法通常是静态方法协助我们把对象创建出来。
在Executors.newFixedThreadPoll()是不会设定固定值的这里是按需创建用完之后也不会立即销毁留着以备后用。
下面我们来给大家演示一下代码展示
package Time;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;//线程池的使用
public class ThreadDemo3 {public static void main(String[] args) {//创建一个线程池ExecutorService pool Executors.newFixedThreadPool(10);//添加任务到线程池中pool.submit(new Runnable() {Overridepublic void run() {System.out.println(hello);}});}
}结果展示 说道这里我们就不得不去看一下Java的官方文档中对线程池的解释了。
我打开Java的官方文档没有的同学可以点击这个链接进入☞Java Platform SE 8
进入之后点击下面的进入ThreadPoolExecutor的页面。 我们可以看到它的参数有以下几个 我们分别给大家解释一下
corePollSize核心线程数如果类比一家公司的话那么他们就是公司里面的正式员工。maximumPollSize最大线程数相当于是公司中的正式员工实习生。如果当前的任务比较多线程池就会多创建一些“临时线程”。如果当前任务比较少比较空闲了线程池就会把多创建出来的临时线程给销毁。也就相当于在公司里面如果任务比较多的话就多招几个实习生但是如果任务不多的话就辞退实习生保留正式员工。KeepAliveTime线程的存活时间如果任务不多了那么临时创建的线程也不是一下子就销毁的而是保留一段时间在销毁相当于是在公司中如果任务不多的话实习生也不是瞬间就被辞退了而是观察一段时间看公司是不是长时间要处于一个不忙的状态。unit时间单位。workQueue线程池也要管理很多任务这些任务也是通过阻塞队列来组织的程序猿可以手动指定给线程池一个队列此时程序猿就很方便的可以控制/获取队列中的信息了submit方法其实就是把任务放到该队列中。threadFactor工程模式创建线程的辅助的类。handler 线程池的拒绝策略如果线程池的池子满了继续往里添加任务那么该如何进行拒绝呢我们接着往下看。
关于线程池的拒绝策略标准库给我们提供了四种。 下面来给大家分别解释一下
ThreadPoolExecutor.AbortPolicy表示如果任务满了继续添加任务添加的操作就会直接抛出异常。ThreadPoolExecutor.CallerRunsPolicy添加的线程自己负责执行这个任务。ThreadPoolExecutor.DiscardOldestPolicy丢弃最老的任务。ThreadPoolExecutor.DiscardPolicy丢弃最新的任务。
3.实现线程池
下面我们就自己来实现一个线程池。
代码展示
package Time;import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;//自己实现的线程池
class MyThreadPool{//阻塞队列用来存放任务private BlockingDequeRunnable queue new LinkedBlockingDeque();public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}//此处实现一个固定线程数的线程池public MyThreadPool(int n) {for (int i 0; i n; i) {Thread t new Thread(() - {try {while (true) {//此处需要让线程池内部有一个while循环不停的取任务Runnable runnable queue.take();runnable.run();}} catch (InterruptedException e) {e.printStackTrace();}});t.start();}}
}
public class ThreadDemo4 {public static void main(String[] args) throws InterruptedException {MyThreadPool pool new MyThreadPool(10);for (int i 0; i 1000; i) {int number i;pool.submit(new Runnable() {Overridepublic void run() {System.out.println(hello number);}});Thread.sleep(3000);}}
}结果展示
此处我们可以看到线程池中任务的执行顺序和添加顺序不一定是相同的这是非常正常的因为这是个线程的调度是无序的。
结束语
这节小编就与大家分享到这里啦这节中小编主要与大家分享了什么是线程池带着大家一起看了标准库中的线程池并且我们自己还实现了一遍希望这节对大家线程池有一定了解想要学习的同学记得关注小编和小编一起学习吧如果文章中有任何错误也欢迎各位大佬及时为小编指点迷津在此小编先谢过各位大佬啦