Java并发线程之线程池的知识总结

yizhihongxing

Java并发线程之线程池的知识总结

线程池的概念

线程池是一种线程使用模式。线程池中包含了一组线程,线程池可以用来控制创建线程的数量和频率,降低了系统资源消耗率。当有新任务需要执行时,可以直接使用已经存在线程,而不是重新创建新的线程。

线程池的用途

线程池的主要作用是:
* 重用线程
* 控制线程数量,避免线程数量过多,导致系统资源的消耗和浪费
* 提高线程的创建、销毁效率

线程池的实现

Java中的线程池是通过Executor框架实现的。 Executor框架提供了一个线程池的标准接口,具体实现由ThreadPoolExecutor类实现。

ThreadPoolExecutor类的构造方法

ThreadPoolExecutor有多个构造方法,这里简单介绍最常用的一个构造方法:

public ThreadPoolExecutor(int corePoolSize, //线程池中核心线程的数量
                          int maximumPoolSize, //线程池中最大线程数量
                          long keepAliveTime, //非核心线程的空闲时间超时,超时就会被销毁
                          TimeUnit unit,    //keepAliveTime的时间单位,通常设置为秒或者毫秒
                          BlockingQueue<Runnable> workQueue, //线程池中缓存任务的队列
                          ThreadFactory threadFactory,  //线程工厂,用于创建新的线程
                          RejectedExecutionHandler handler) //拒绝策略,当任务添加到线程池失败后的处理方法

线程池的参数介绍

corePoolSize

表示线程池中的核心线程数量。当新任务添加到线程池中时,如果当前运行的线程数小于corePoolSize,那么就创建新的线程来处理请求。如果当前运行的线程数大于或等于corePoolSize,则把任务添加到线程池的工作队列中去。

maximumPoolSize

表示线程池中最大线程数量。当缓存队列满了之后,如果还有新的任务要处理,则会创建新的线程去处理新的任务。但是创建线程数不能超过maximumPoolSize。如果当前运行的线程数已经达到maximumPoolSize,那么就会根据拒绝策略RejectedExecutionHandler来决定如何处理新的任务。

keepAliveTime

表示非核心线程的空闲时间超时,超时就会被销毁。这里的非核心线程是指当前运行的线程数量大于corePoolSize的线程。

unit

表示keepAliveTime的时间单位,通常设置为秒或者毫秒。

workQueue

表示线程池中缓存任务的队列。当新任务添加到线程池中时,如果当前运行的线程数已经达到corePoolSize,那么新的任务就会被添加到workQueue队列中去。

threadFactory

表示创建线程的工厂,用于创建新的线程。

handler

表示拒绝策略,当任务添加到线程池失败后的处理方法。Java提供了4种拒绝策略:
* AbortPolicy(终止策略):如果无法处理新请求,则快速失败并抛出RejectedExecutionException异常。
* CallerRunsPolicy(调用者策略):调用提交任务的线程来处理该任务。
* DiscardOldestPolicy(丢弃旧任务策略):丢弃队列中等待最久的任务,并将当前任务加入队列中。
* DiscardPolicy(丢弃策略):丢弃无法处理的任务。

线程池的示例

下面是一个简单的线程池示例,展示了如何使用线程池:

public class ThreadPoolExample {

    public static void main(String[] args) {

        // 创建线程池
        ExecutorService executorService =
                new ThreadPoolExecutor(2, // 核心线程数为2
                        5, // 最大线程数为5
                        100, // 超时时间为100毫秒
                        TimeUnit.MILLISECONDS,
                        new LinkedBlockingQueue<>(10), // 缓冲队列的大小为10
                        Executors.defaultThreadFactory(),
                        new ThreadPoolExecutor.AbortPolicy()); // 线程池满了后,抛出异常

        // 执行10个任务
        for (int i = 0; i < 10; i++) {
            executorService.execute(new Task(i));
        }

        // 关闭线程池
        executorService.shutdown();
    }

    static class Task implements Runnable {
        private int taskId;

        public Task(int taskId) {
            this.taskId = taskId;
        }

        @Override
        public void run() {
            System.out.println("Task " + taskId + " is running on " + Thread.currentThread().getName());
        }
    }
}

上述示例代码中,通过ThreadPoolExecutor类创建一个线程池executorService,并设置了线程池的核心线程数为2,最大线程数为5,超时时间为100毫秒,缓冲队列的大小为10,拒绝策略为线程池满了后,抛出异常。

然后,执行10个任务,每个任务都是一个Task对象,打印任务编号和运行的线程名。

自定义线程池

除了使用ThreadPoolExecutor提供的构造方法创建线程池外,也可以通过自定义方式来创建线程池,从而满足特定的业务需求,例如使用特定的拒绝策略或使用特定的队列。

下面是一个自定义线程池的示例:

public class CustomThreadPool {

    public static void main(String[] args) {

        // 创建自定义线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                1, // corePoolSize
                2, // maximumPoolSize
                60, // keepAliveTime
                TimeUnit.SECONDS, // 时间单位
                new ArrayBlockingQueue<>(3), // 队列容量
                Executors.defaultThreadFactory(), // 线程工厂
                new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略

        for (int i = 0; i < 5; i++) {
            try {
                // 添加任务到线程池
                executor.execute(new Task(i));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        // 关闭线程池
        executor.shutdown();
    }

    static class Task implements Runnable {
        private int taskId;

        public Task(int taskId) {
            this.taskId = taskId;
        }

        @Override
        public void run() {
            try {
                System.out.println("Task " + taskId + " is running on " + Thread.currentThread().getName());
                Thread.sleep(3000);
                System.out.println("Task " + taskId + " is completed.");
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }
}

上述示例代码中,通过ThreadPoolExecutor类创建线程池executor,并自定义了核心线程数为1,最大线程数为2,超时时间为60秒,队列容量为3,线程工厂使用默认,拒绝策略为CallerRunsPolicy,即调用提交任务的线程来处理该任务。

然后,通过for循环将5个任务添加到线程池executor中;每个任务都是一个Task对象,打印任务编号和运行的线程名。

最后,关闭线程池executor。由于自定义的线程池是异步的,因此可能会有一些任务尚未完成,但是当主线程结束时,所有任务也会被结束。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发线程之线程池的知识总结 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • PHP高并发和大流量解决方案整理

    PHP高并发和大流量解决方案整理 在如今互联网时代,高并发和大流量是所有Web开发中必须要解决的问题。在PHP开发中,如何解决高并发和大流量成为了开发者不可避免地要面对的问题。本文将为大家介绍PHP高并发和大流量的解决方案。 1. 前端优化 1.1 页面压缩 通过GZIP压缩可以减少传输的数据量,从而提升网页加载速度。可以通过修改Apache或Nginx的配…

    多线程 2023年5月16日
    00
  • Java多线程之Interrupt中断线程详解

    Java多线程之Interrupt中断线程详解 在使用Java进行多线程编程时,经常需要控制线程的执行行为,比如暂停、终止、恢复线程等。这时我们就需要一个中断机制来实现我们的控制需求。Java中,通过Interrupt中断机制来实现对线程的中断控制。 中断线程的基本使用方法: 要中断一个Java线程,可以使用线程对象的interrupt()方法,其语法为: …

    多线程 2023年5月17日
    00
  • 如何利用Golang写出高并发代码详解

    这里是如何利用Golang写出高并发代码的攻略: 什么是高并发 高并发是指系统在处理大量请求时,能够保持稳定性和高效性的特性。通常情况下,高并发是指单秒内能够处理数万个请求。 Golang 的 Goroutines 和 Channels 在 Golang 中,利用 goroutines 和 channels 可以轻松地编写高并发程序。 Goroutines …

    多线程 2023年5月17日
    00
  • 高并发下如何避免重复数据产生技巧

    如何避免重复数据产生,在高并发环境下是一个非常重要的问题,因为一旦出现重复数据,就会影响整个系统的正常运行,甚至可能导致严重的数据安全问题。下面是一些可以避免重复数据产生的技巧: 数据库级别的锁定机制 在高并发环境下,一个经典的问题是“在同一时刻是否可以有多个用户同时修改同一条数据?” 事实上,这是不可能的,因为如果多个用户同时修改同一条数据,就会出现数据不…

    多线程 2023年5月17日
    00
  • Android中创建多线程管理器实例

    创建多线程管理器实例可以帮助Android应用更好地管理并发任务。 下面是创建多线程管理器实例的步骤: 步骤一:创建一个新线程类 在Android应用中,可以通过创建一个新线程类来运行单独的任务。新线程类继承自Thread类,通过覆盖run()方法来定义要运行的任务内容。 下面是一个新线程类的示例: public class MyThread extends…

    多线程 2023年5月16日
    00
  • 详解MySQL多版本并发控制机制(MVCC)源码

    详解MySQL多版本并发控制机制(MVCC)源码 一、MVCC简介 MVCC(Multi-Version Concurrency Control)即多版本并发控制,是MySQL的一种高性能的事务处理方式。 MVCC基于快照的概念,即每个事务在执行时都会在内部生成一份数据快照,用于记录当前时刻的数据状态。当有其他事务需要读取数据时,它们实际上访问的是已经生成的…

    多线程 2023年5月17日
    00
  • Java并发LinkedBlockingQueue源码分析

    Java并发LinkedBlockingQueue源码分析 简单介绍 LinkedBlockingQueue是Java并发包中提供的一个阻塞队列实现,它支持在队列两端添加或取出元素,并具有阻塞功能。具体来说,当队列为空时,从队列尾部加入元素的操作将被阻塞;当队列满时,从队列头部取出元素的操作将被阻塞。 源码解析 内部类:Node 在LinkedBlockin…

    多线程 2023年5月16日
    00
  • 详解Java多线程与并发

    详解Java多线程与并发攻略 Java多线程与并发是Java编程中非常重要的一个部分,它可以提高程序的效率和运行速度。本文将详细介绍Java多线程与并发的相关知识和技巧。包括线程创建、线程安全、synchronized关键字、volatile关键字等。 线程创建 Java创建线程的方法有两种: 继承Thread类并重写run()方法。 示例代码: publi…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部