企业网站模板免费版,怎么自建一个网站,深圳网站建设,asp.net 做电子购物网站的网银结算功能如何实现的1.Java 中的线程池是如何实现的
Java中的线程池主要通过java.util.concurrent包提供的Executor框架实现。线程池的核心是重用一组现有线程来执行任务#xff0c;而不是为每个任务创建新线程。这样做可以减少因频繁创建和销毁线程带来的开销#xff0c;提高系统资源的利用率而不是为每个任务创建新线程。这样做可以减少因频繁创建和销毁线程带来的开销提高系统资源的利用率并提供更好的系统性能。在Java中线程池的实现主要依赖于以下几个关键类
1. Executor接口
Executor是最基础的接口它提供了一个execute(Runnable command)方法用于执行任务。然而这个接口本身并不直接提供线程池功能。
2. ExecutorService接口
ExecutorService是Executor的子接口提供了更丰富的线程池管理功能包括任务提交、线程池关闭等。它定义了一系列方法允许对任务的提交进行更细致的控制并能返回任务的执行结果。
3. ThreadPoolExecutor类
ThreadPoolExecutor是ExecutorService接口的一个实现类提供了线程池的实现。它允许配置线程池的核心参数如核心线程数、最大线程数、线程存活时间、任务队列等。ThreadPoolExecutor是实现线程池的直接方式。
4. ScheduledExecutorService接口
ScheduledExecutorService是ExecutorService的子接口提供了任务的定时执行和周期性执行功能。
5. ScheduledThreadPoolExecutor类
ScheduledThreadPoolExecutor是ScheduledExecutorService接口的实现类支持任务的定时执行和周期性执行。
实现原理
任务队列线程池使用一个阻塞队列来存储待执行的任务。当所有线程都忙时新提交的任务会被放入队列中等待。线程管理线程池根据配置的参数如核心线程数、最大线程数来创建和管理线程。当任务提交给线程池时如果核心线程都在忙且任务队列未满则任务会被加入队列。如果核心线程都在忙且任务队列已满线程池会创建新的线程来处理任务直到线程数达到最大线程数限制。线程回收当线程空闲时间超过配置的存活时间时线程池可能会回收线程以节省资源。
示例
创建固定大小的线程池并提交任务
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo {public static void main(String[] args) {// 创建一个固定大小的线程池ExecutorService executor Executors.newFixedThreadPool(4);// 提交任务给线程池执行for (int i 0; i 10; i) {int taskId i;executor.execute(() - {System.out.println(Executing task taskId inside : Thread.currentThread().getName());});}// 关闭线程池executor.shutdown();}
}在这个示例中通过Executors.newFixedThreadPool(4)创建了一个固定大小为4的线程池然后提交了10个任务。线程池会重用这4个线程来执行所有提交的任务。
2.创建线程池的几个核心构造参数
在Java中通过ThreadPoolExecutor类创建线程池时需要指定几个核心构造参数这些参数对线程池的行为和性能有重要影响。以下是这些核心构造参数
1. corePoolSize
类型int描述线程池的基本大小即在没有任务执行时线程池的大小并且只有在工作队列满了之后才会创建超过这个数量的线程。
2. maximumPoolSize
类型int描述线程池允许的最大线程数。如果队列满了并且已创建的线程数小于最大线程数则线程池会再创建新的线程执行任务。
3. keepAliveTime
类型long描述当线程数大于核心线程数时这是多余空闲线程在终止前等待新任务的最长时间。
4. unit
类型TimeUnit描述keepAliveTime参数的时间单位。TimeUnit是一个枚举提供了如TimeUnit.SECONDS、TimeUnit.MILLISECONDS等时间单位。
5. workQueue
类型BlockingQueueRunnable描述用来存储等待执行的任务的阻塞队列。可以选择不同类型的队列如LinkedBlockingQueue、ArrayBlockingQueue等不同类型的队列在处理不同类型的任务时效率不同。
6. threadFactory可选
类型ThreadFactory描述用于设置创建线程的工厂。可以通过实现ThreadFactory接口自定义线程创建方式如设置线程名、优先级等。
7. handler可选
类型RejectedExecutionHandler描述当任务无法被线程池执行时例如队列已满且线程数已达到最大值拒绝任务的处理程序。常见的有四种策略ThreadPoolExecutor.AbortPolicy抛出异常、ThreadPoolExecutor.CallerRunsPolicy调用者运行任务、ThreadPoolExecutor.DiscardPolicy忽略任务、ThreadPoolExecutor.DiscardOldestPolicy丢弃队列最前面的任务然后重试执行任务。
示例
import java.util.concurrent.*;public class ThreadPoolExample {public static void main(String[] args) {int corePoolSize 5;int maximumPoolSize 10;long keepAliveTime 5000;TimeUnit unit TimeUnit.MILLISECONDS;BlockingQueueRunnable workQueue new LinkedBlockingQueue(100);ThreadPoolExecutor executor new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());executor.execute(() - {System.out.println(Task is running.);});executor.shutdown();}
}在这个示例中创建了一个ThreadPoolExecutor实例并指定了核心构造参数然后提交了一个简单的任务来执行。
3.线程池中的线程是怎么创建的是一开始就随着线程池的启动创建好的吗线程池中线程的创建方式主要取决于线程池的配置参数和实际运行时的任务需求。线程池中线程的创建和管理遵循以下基本规则
初始化核心线程
立即创建在某些线程池配置中可以选择在线程池创建时立即初始化并启动核心线程数corePoolSize即使没有任务提交。这可以通过调用ThreadPoolExecutor的prestartCoreThread()或prestartAllCoreThreads()方法实现。按需创建默认情况下核心线程是按需创建的即只有在任务被提交并且当前运行的线程数小于corePoolSize时才会创建和启动新的线程。
超过核心线程数的线程创建
当所有核心线程都在忙碌并且内部任务队列已满时如果当前线程总数小于最大线程数maximumPoolSize线程池会创建新的线程来处理任务。这些超出核心线程数的线程在空闲时会存在一段时间由keepAliveTime参数控制如果在这段时间内没有新的任务分配给它们它们将被回收。
线程创建的实际流程
任务提交当一个任务被提交到线程池时线程池会进行如下判断 如果当前运行的线程数小于corePoolSize则创建并启动一个新的线程来执行提交的任务即使其他工作线程空闲。如果当前运行的线程数等于或大于corePoolSize但任务队列未满任务会被加入队列等待执行。如果任务队列已满并且当前运行的线程数小于maximumPoolSize线程池会尝试创建新的线程来直接执行任务。如果当前运行的线程数达到maximumPoolSize新提交的任务会被拒绝执行处理器处理。
通过这种机制线程池可以有效地管理线程的创建和销毁以适应不同的工作负载避免在高负载下创建过多的线程导致资源耗尽同时也避免在低负载时保持过多的空闲线程导致资源浪费。