温州网站建设方案维护,佛山建设网站公司哪家好,网易邮箱企业版,wordpress getthetags目录 java线程池
线程池应用场景#xff1a;
如何创建线程池#xff1a;
有什么区别#xff1a;
不同线程池对应的应用场景
案例
输出结果 java线程池
Java线程池是一种预先创建一定数量的线程#xff0c;并将任务提交给这些线程执行的机制。线程池可以避免频繁创建…目录 java线程池
线程池应用场景
如何创建线程池
有什么区别
不同线程池对应的应用场景
案例
输出结果 java线程池
Java线程池是一种预先创建一定数量的线程并将任务提交给这些线程执行的机制。线程池可以避免频繁创建和销毁线程提高程序的性能和响应速度。
为什么要创建线程池
降低资源消耗通过重复利用已创建的线程避免线程的频繁创建和销毁降低资源消耗。提高响应速度当任务到达时任务不需要等待线程创建就能立即执行。提高线程的可管理性线程池可以进行统一的分配、调优和监控有利于提高线程的可管理性。
线程池应用场景
快速响应用户请求IO密集型任务如用户要查看商品信息需要将商品维度的一系列信息聚合起来展示给用户。通过使用线程池可以快速响应用户请求。快速处理批量任务CPU密集型任务如统计某个报表需要计算出全国各个门店中有哪些商品有某种属性用于后续营销策略的分析。通过使用线程池可以快速处理批量任务。
如何创建线程池
Java中的线程池可以通过以下几种方式创建
Executors.newFixedThreadPool创建一个固定大小的线程池可控制并发的线程数超出的线程会在队列中等待。方法只有一个参数即线程池的大小。Executors.newCachedThreadPool创建一个可缓存的线程池若线程数超过处理所需缓存一段时间后会回收若线程数不够则新建线程。Executors.newSingleThreadExecutor创建一个单个线程数的线程池它可以保证先进先出的执行顺序。Executors.newScheduledThreadPool创建一个可以执行延迟任务的线程池。ThreadPoolExecutor通过ThreadPoolExecutor类创建线程池可以自定义线程池的参数如核心线程数、最大线程数、队列类型等。
有什么区别
使用 Executors 工厂类中的 newCachedThreadPool() 和 newFixedThreadPool() 方法
优点
- 使用起来比较简单不需要自己手动管理线程池的状态 - 可以快速创建线程池。
缺点
- 无法自定义线程池的大小和饱和策略 - 不够灵活。
使用 Executors 工厂类中的 newSingleThreadExecutor() 方法
优点
- 创建单个线程的线程池 - 适用于需要顺序执行任务的场景。
缺点
- 无法自定义线程池的大小和饱和策略 - 不够灵活。
使用 ThreadPoolExecutor 类来创建线程池
参数
- corePoolSize核心线程数 - maximumPoolSize最大线程数 - keepAliveTime线程存活时间 - unit时间单位 - workQueue任务队列 - threadFactory线程工厂 - handler饱和策略
优点
- 可以根据实际情况来自定义线程池的大小、任务队列等 - 可以灵活地设置饱和策略。
缺点
- 对于不熟悉线程池的开发人员来说使用起来比较麻烦 - 需要手动管理线程池的状态。
核心线程数指线程池中保持活动的最小线程数。如果线程池中的当前线程数小于核心线程数则会在需要时创建新的线程。最大线程数指线程池中允许的最大线程数。如果队列满了并且当前线程数已经达到最大线程数则会在需要时创建新的线程。队列类型指用于存储待执行任务的队列类型。常见的队列类型有直接提交队列、有界队列、无界队列等。拒绝策略指当任务队列已满且所有线程都在工作但仍然无法处理新任务时的处理策略。常见的拒绝策略有抛出异常、拒绝任务、阻塞任务等。
以上几种方式分别对应不同的应用场景和需求。其中Executors类提供了一种简单的方式来创建线程池但它的参数相对固定不适合进行复杂的配置。而ThreadPoolExecutor类则提供了更多的参数选项可以灵活地配置线程池的各种属性适用于更为复杂的场景。
不同线程池对应的应用场景
Executors.newFixedThreadPool适用于需要控制并发线程数量的场景例如当需要确保每个请求都能得到响应时或者当请求量很大时可以控制并发线程数量避免系统过载。-------需要创建固定数量的线程来执行长时间运行的任务Executors.newCachedThreadPool适用于执行大量短期异步任务例如Web请求处理或短期的后台任务。这种线程池能快速创建和销毁线程以应对大量突发任务。大量短时间的任务如网络请求Executors.newSingleThreadExecutor适用于需要保证任务按照提交顺序执行的场景例如当需要保证任务的串行执行时。需要顺序执行任务的场景如一个线程代表一个用户请求Executors.newScheduledThreadPool适用于需要定时或周期性执行任务的场景例如定时任务、定时备份等。ThreadPoolExecutor适用于需要自定义线程池参数的场景例如需要根据任务的特性如优先级、执行时间等来调整线程池的配置。这种线程池提供了更多的灵活性和控制性。复杂的应用场景需要根据实际情况来动态地调整线程池的大小和饱和策略如一个 Web 服务器上服务对多个用户的请求时
案例
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;/*** 线程处理类*/
public class ExecutorProcessPool {private ExecutorService executor;private static ExecutorProcessPool pool new ExecutorProcessPool();private final int threadMax 10;private ExecutorProcessPool() {System.out.println(threadMax threadMax);executor ExecutorServiceFactory.getInstance().createFixedThreadPool(threadMax);}public static ExecutorProcessPool getInstance() {return pool;}/*** 关闭线程池这里要说明的是调用关闭线程池方法后线程池会执行完队列中的所有任务才退出*/public void shutdown() {executor.shutdown();}/*** 提交任务到线程池可以接收线程返回值** param task* return*/public Future? submit(Runnable task) {return executor.submit(task);}/*** 提交任务到线程池可以接收线程返回值** param task* return*/public Future? submit(Callable? task) {return executor.submit(task);}/*** 直接提交任务到线程池无返回值** param task*/public void execute(Runnable task) {executor.execute(task);}}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;/*** 线程池构造工厂*/
public class ExecutorServiceFactory {private static ExecutorServiceFactory executorFactory new ExecutorServiceFactory();/*** 定时任务线程池*/private ExecutorService executors;private ExecutorServiceFactory() {}/*** 获取ExecutorServiceFactory** return*/public static ExecutorServiceFactory getInstance() {return executorFactory;}/*** 创建一个线程池它可安排在给定延迟后运行命令或者定期地执行。** return*/public ExecutorService createScheduledThreadPool() {// CPU个数int availableProcessors Runtime.getRuntime().availableProcessors();// 创建executors Executors.newScheduledThreadPool(availableProcessors * 10, getThreadFactory());return executors;}/*** 创建一个使用单个 worker 线程的* Executor以无界队列方式来运行该线程。注意如果因为在关闭前的执行期间出现失败而终止了此单个线程* 那么如果需要一个新线程将代替它执行后续的任务。可保证顺序地执行各个任务并且在任意给定的时间不会有多个线程是活动的。与其他等效的* newFixedThreadPool(1) 不同可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。** return*/public ExecutorService createSingleThreadExecutor() {// 创建executors Executors.newSingleThreadExecutor(getThreadFactory());return executors;}/*** 创建一个可根据需要创建新线程的线程池但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言这些线程池通常可提高程序性能。调用* execute 将重用以前构造的线程如果线程可用。如果现有线程没有可用的则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60* 秒钟未被使用的线程。因此长时间保持空闲的线程池不会使用任何资源。注意可以使用 ThreadPoolExecutor* 构造方法创建具有类似属性但细节不同例如超时参数的线程池。** return*/public ExecutorService createCachedThreadPool() {// 创建executors Executors.newCachedThreadPool(getThreadFactory());return executors;}/*** 创建一个可重用固定线程数的线程池以共享的无界队列方式来运行这些线程。在任意点在大多数 nThreads* 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务* 则在有可用线程之前附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止* 那么一个新线程将代替它执行后续的任务如果需要。在某个线程被显式地关闭之前池中的线程将一直存在。** return*/public ExecutorService createFixedThreadPool(int count) {// 创建executors Executors.newFixedThreadPool(count, getThreadFactory());return executors;}/*** 获取线程池工厂** return*/private ThreadFactory getThreadFactory() {return new ThreadFactory() {AtomicInteger sn new AtomicInteger();public Thread newThread(Runnable r) {SecurityManager s System.getSecurityManager();ThreadGroup group (s ! null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();Thread t new Thread(group, r);t.setName(任务线程 - sn.incrementAndGet());return t;}};}
}import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;/*** 测试类*/
public class ExecutorTest {public static void main(String[] args) {ExecutorProcessPool pool ExecutorProcessPool.getInstance();/* for (int i 0; i 200; i) {Future? future pool.submit(new ExcuteTask1(i));
// try {
// 如果接收线程返回值future.get() 会阻塞如果这样写就是一个线程一个线程执行。所以非特殊情况不建议使用接收返回值的。
// System.out.println(future.get());
// } catch (Exception e) {
// e.printStackTrace();
// }}*/ListString list new ArrayList(Arrays.asList(a, b, c, d, e, f, g, h, i, j, k, l, n, m, o, p));for (int i 0; i list.size(); i) {String s list.get(i);pool.execute(new ExcuteTask2(s ));}//关闭线程池如果是需要长期运行的线程池不用调用该方法。//监听程序退出的时候最好执行一下。ListString list2 new ArrayList(Arrays.asList(的, 飞, 个, 个, 3));for (int i 0; i list2.size(); i) {String s list2.get(i);pool.execute(new ExcuteTask2(s ));}
// pool.shutdown();}/*** 执行任务1实现Callable方式*/static class ExcuteTask1 implements CallableString {private String taskName;public ExcuteTask1(String taskName) {this.taskName taskName;}Overridepublic String call() throws Exception {try {
// Java 6/7最佳的休眠方法为TimeUnit.MILLISECONDS.sleep(100);
// 最好不要用 Thread.sleep(100);TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 1000));// 1000毫秒以内的随机数模拟业务逻辑处理} catch (Exception e) {e.printStackTrace();}System.out.println(-------------这里执行业务逻辑Callable TaskName taskName -------------);return 线程返回值Callable TaskName taskName ;}}/*** 执行任务2实现Runable方式*/static class ExcuteTask2 implements Runnable {private String taskName;public ExcuteTask2(String taskName) {this.taskName taskName;}Overridepublic void run() {try {TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 1000));// 1000毫秒以内的随机数模拟业务逻辑处理} catch (Exception e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() -------------这里执行业务逻辑Runnable TaskName taskName -------------);}}
}
输出结果