Java线程池创建方式和应用场景

简介: Java线程池创建方式和应用场景

1.什么是线程池?

2 线程池创建种类

2.1通过线程池代码创建线程

 public void two() throws Exception{
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int count=0;
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(1200);
                    count++;
                }
                return count;
            }
        };
        ExecutorService e= Executors.newFixedThreadPool(10);
        Future<Integer> f1=e.submit(callable);
        Integer result = f1.get();
        System.out.println("获取多线程的值:"+result);
    }

通过上述代码,我们可以知道实现线程池涉及到ExecutorService和Executors。下面我们来一个个进行源码分析

2.1.Executors创建的线程池

在idea中,把光标放到Executors上,按住鼠标左键+ctrl进入Executors类。输入alt+7查看该类下的所有方法。

2.1.1 newFixedThreadPool重用固定数量线程的线程池

创建一个重用固定数量线程的线程池,如果在所有线程都处于活动状态时提交了额外的任务,他们将在队列中等待,直到线程可用为止。

public class FixedThreadPoolDemo {
    public static void main(String[] args) {
        // 创建 2 个线程的线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        // 创建任务
        Runnable runnable = () -> System.out.println("任务被执行,线程:" + Thread.currentThread().getName());
        // 线程池执行任务(一次添加 8 个任务)
        threadPool.execute(runnable);
        threadPool.execute(runnable);
        threadPool.execute(runnable);
        threadPool.execute(runnable);
        threadPool.execute(runnable);
        threadPool.execute(runnable);
        threadPool.execute(runnable);
        threadPool.execute(runnable);
    }
}

8da5f137f3b04f4f98a0e90c307ede18.png

2.1.2 newWorkStealingPool(int parallelism)抢占式执行的线程池

jdk1.8后引入的,它是新的线程池类ForkJoinPool的扩展,能够合理的使用CPU,进行并发运行任务。

创建一个线程池,维护足够的线程以支持给定的并行度级别,并且可以使用多个队列来减少争用

    // 创建一个线程池,维护足够的线程以支持给定的并行度级别,并且可以使用多个队列来减少争用。
        // 并行度级别对应于主动参与或可用于参与任务处理的最大线程数。
        // 线程的实际数量可能会动态增长和收缩。
        // 工作窃取池不保证提交任务的执行顺序。
        // 并行度——目标并行度级别
        //一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行。
        ExecutorService forkJoin = Executors.newWorkStealingPool();
        forkJoin.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("i====>" + 1);
            }
        });
        forkJoin.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("i====>" + 2);
            }
        });
        forkJoin.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("i====>" + 3);
            }
        });
        forkJoin.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("i====>" + 4);
            }
        });
        forkJoin.shutdown();

2.1.3 newSingleThreadExecutor()单例的线程池

创建一个单例的线程池,也就是说池中就一个线程。通过这个线程来处理所有的任务,如果发现这个这个线程因为失败而关闭,不要慌,会有一个线程来取代他,保证任务能正常的运转

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NewSingleThreadExecutor {
    public static void main(String[] args) {
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final  int index=i;
            singleThreadExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(index == 5){   //故意搞破坏
                        int flag =index/0;
                    }
                    System.out.println(Thread.currentThread().getName());
                }
            });
        }
    }
}

2.1.4 newCachedThreadPool()可缓存的线程池

创建一个可缓存的线程池,若线程数超过所需,那么多余的线程会被缓存一段时间后再回收,若线程数不够,则会新建线程。

public class CachedThreadPoolDemo {
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService threadPool = Executors.newCachedThreadPool();
        // 执行任务
        for (int i = 0; i < 5; i++) {
            threadPool.execute(() -> {
                System.out.println("任务被执行,线程:" + Thread.currentThread().getName());
            });
        }
    }
}

2.1.5 newSingleThreadScheduledExecutor()单线程的可以执行延迟任务的线程池

创建一个单线程的可以执行延迟任务的线程池。这种线程池可以看做是 ScheduledThreadPool 的单线程版本。

public class SingleThreadScheduledExecutorDemo {
    public static void main(String[] args) {
        // 创建线程池
        ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
        // 添加定时执行任务(2s 后执行)
        System.out.println("添加任务,时间:" + new Date());
        threadPool.schedule(() -> {
            System.out.println("任务被执行,时间:" + new Date());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
            }
        }, 2, TimeUnit.SECONDS);
    }
}

2.1.6 newScheduledThreadPool(int corePoolSize)周期性的运行任务线程池

此线程池的的线程可以定时周期性的运行任务。注意坑点:使用这种方法,如果出现异常,会导致无法正常的运行任务。所以,个人建议,使用这种方式的时候,run方法里面的代码可以加上异常处理逻辑。这种方式newSingleThreadExecutor类似,只是增加了周期性运行,这里不过多的阐述。

101f9748ff24466181628887244513e9.png

public class NewScheduledThreadPool {
    public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("开始时间:"+Thread.currentThread().getName()+","+new Date());
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },2000,6000,TimeUnit.MILLISECONDS);
    }
}

通过截图我们可以发现是6秒一次。

保证period>initialDelay,以period为准。以period的时长为一个周期

如果run方法运行时间大于period,定时任务的周期以run运行时长为一个周期。


目录
相关文章
|
2月前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
5天前
|
人工智能 搜索推荐 算法
【潜意识Java】人工智能与Java的有关应用场景
本文介绍了如何使用Java和Apache Mahout实现一个基于协同过滤的推荐系统。
15 1
|
19天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
80 17
|
2月前
|
Prometheus 监控 Cloud Native
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
235 64
|
1月前
|
监控 Java API
探索Java NIO:究竟在哪些领域能大显身手?揭秘原理、应用场景与官方示例代码
Java NIO(New IO)自Java SE 1.4引入,提供比传统IO更高效、灵活的操作,支持非阻塞IO和选择器特性,适用于高并发、高吞吐量场景。NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector),能实现多路复用和异步操作。其应用场景涵盖网络通信、文件操作、进程间通信及数据库操作等。NIO的优势在于提高并发性和性能,简化编程;但学习成本较高,且与传统IO存在不兼容性。尽管如此,NIO在构建高性能框架如Netty、Mina和Jetty中仍广泛应用。
46 3
|
1月前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
|
1月前
|
监控 Java 开发者
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####
|
2月前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
126 38
|
2月前
|
存储 缓存 监控
Java中的线程池深度解析####
本文深入探讨了Java并发编程中的核心组件——线程池,从其基本概念、工作原理、核心参数解析到应用场景与最佳实践,全方位剖析了线程池在提升应用性能、资源管理和任务调度方面的重要作用。通过实例演示和性能对比,揭示合理配置线程池对于构建高效Java应用的关键意义。 ####
|
2月前
|
Prometheus 监控 Cloud Native
在 Java 中,如何使用线程池监控以及动态调整线程池?
【10月更文挑战第22天】线程池的监控和动态调整是一项重要的任务,需要我们结合具体的应用场景和需求,选择合适的方法和策略,以确保线程池始终处于最优状态,提高系统的性能和稳定性。
505 2