jdk线程池的实现

关于“jdk线程池的实现”的攻略,我们可以分为以下几个部分来讲解:

1. 线程池原理和作用

线程池是一种常用的异步并发编程技术。其作用是在程序运行时提前创建一定数量的线程,这些线程被用来执行一些任务,一旦任务执行完毕,线程不会被销毁,而是等待被下一个任务调用。这样可以减少线程的创建和销毁,提高程序的性能和稳定性。

2. jdk线程池的实现

在JDK中,提供了一个ThreadPoolExecutor类来实现线程池。通过这个类,我们可以定义线程池的大小、任务队列的大小以及拒绝策略等属性。其构造方法如下:

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, 
                          BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

各个参数的含义如下:

  • corePoolSize:线程池中核心线程的数量,即初始化时创建的线程数。
  • maximumPoolSize:线程池中最大线程数量。
  • keepAliveTime:非核心线程的空闲存活时间,超过此时间将被回收。
  • unit:时间单位。
  • workQueue:任务队列。
  • threadFactory:线程工厂,用于创建新线程。
  • handler:拒绝策略,用于处理任务队列已满的情况。

例如,我们可以这样创建一个线程池:

ExecutorService threadPool = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS, 
                                                     new LinkedBlockingQueue<Runnable>(), 
                                                     Executors.defaultThreadFactory(), 
                                                     new ThreadPoolExecutor.AbortPolicy());

其中,我们使用了默认的线程工厂和拒绝策略,而任务队列使用了无界阻塞队列。

3. 示例说明

下面我们来看两个示例,分别演示了线程池的基本用法和拒绝策略的应用。

示例1:基本用法

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadPoolDemo {

    static class Task implements Runnable {
        private int taskId;

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

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

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 5; i++) {
            threadPool.execute(new Task(i));
        }
        threadPool.shutdown();
    }
}

在这个示例中,我们通过Executors.newFixedThreadPool(2)来创建一个固定大小为2的线程池。然后,我们创建5个任务并提交给线程池,这时线程池会开启两个线程来执行任务。由于线程池的大小为2,因此只会有两个任务同时执行,而其他任务会被放入任务队列中等待空闲线程的执行。最后,我们调用shutdown()方法来关闭线程池。

输出结果如下:

task 0 running on thread pool-1-thread-1
task 1 running on thread pool-1-thread-2
task 2 running on thread pool-1-thread-1
task 3 running on thread pool-1-thread-2
task 4 running on thread pool-1-thread-1

可以看到,线程池中一共有两个线程在执行任务,并且任务的执行顺序与提交顺序不一定相同。

示例2:拒绝策略

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RejectedExecutionDemo {

    static class Task implements Runnable {
        private int taskId;

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

        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("task " + taskId + " running on thread " + Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2), ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < 6; i++) {
            threadPool.execute(new Task(i));
        }
        threadPool.shutdown();
    }
}

在这个示例中,我们创建了一个容量为2的有界任务队列,并将其作为线程池的任务队列。另外,我们将线程池的最大线程数设置为4,这样线程池一共可以同时执行6个任务。

然后,我们创建6个任务并提交给线程池,这时先执行的两个任务会被分配到空闲的线程中执行;而后续的四个任务则会被放入任务队列中等待执行。此时,任务队列已经满了,而线程池中的线程已经达到了最大值,因此新的任务不再被接受,而是由拒绝策略来处理。在这个示例中,我们使用了默认的拒绝策略ThreadPoolExecutor.AbortPolicy(),它会直接抛出RejectedExecutionException异常。因此,在这个示例中,最后两个任务都无法被执行。

输出结果如下:

task 0 running on thread pool-1-thread-1
task 1 running on thread pool-1-thread-2
task 2 running on thread pool-1-thread-1
task 3 running on thread pool-1-thread-2
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@15bb7f69 rejected from java.util.concurrent.ThreadPoolExecutor@6d06d69c[Running, pool size = 4, active threads = 4, queued tasks = 2, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
    at com.example.demo.RejectedExecutionDemo.main(RejectedExecutionDemo.java:32)

可以看到,在task 4task 5被拒绝执行,并抛出了RejectedExecutionException异常。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:jdk线程池的实现 - Python技术站

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

相关文章

  • Nginx负载均衡以及动静分离的原理与配置

    Nginx是一个高性能的Web服务器和反向代理服务器,可以用于负载均衡和动静分离。本文将讲解Nginx负载均衡及动静分离的原理和配置方法,内容包括以下几个方面: 负载均衡原理及方法 动静分离原理及方法 Nginx配置示例 1. 负载均衡原理及方法 负载均衡主要用于分摊用户请求到多个服务器上,以提高吞吐量、降低延迟和避免单点故障。Nginx基于反向代理实现负载…

    Java 2023年5月20日
    00
  • SpringMVC框架REST架构体系原理分析

    简介 Spring MVC是一个基于Java的Web框架,它提供了一种RESTful架构体系,可以帮助开发人员构建可扩展的Web应用程序。本文将详细介绍Spring MVC框架REST架构体系的原理,并提供两个示例说明。 REST架构体系 REST(Representational State Transfer)是一种基于HTTP协议的Web服务架构体系。它…

    Java 2023年5月17日
    00
  • springboot各种下载文件的方式汇总

    Spring Boot各种下载文件的方式汇总攻略 在Web应用程序中,下载文件是常见的功能之一。Spring Boot提供了多种方式来下载文件。本文将汇总介绍Spring Boot中各种下载文件的方式。 1. 使用OutputStream下载文件 最简单的方式是使用OutputStream将文件写入到HttpServletResponse的输出流,并将相应的…

    Java 2023年5月19日
    00
  • 解决springboot 获取form-data里的file文件的问题

    关于“解决springboot 获取form-data里的file文件的问题”的攻略,我们可以分为以下几个步骤来讲解: 添加相关依赖 在使用Spring Boot的过程中需要引入一些相关依赖,我在这里推荐使用spring-boot-starter-web模块,并且添加spring-boot-starter-tomcat或者spring-boot-starte…

    Java 2023年5月20日
    00
  • 数据库其它

    关于“数据库其它”的攻略,我可以向你分享以下内容: 什么是“数据库其他” 在数据库领域中,通常我们在日常工作中会遇到常见的数据库如MySQL、Oracle、SQL Server等,但是还存在一些相对冷门但是非常有用的数据库,这些数据库就是“数据库其他”。这些数据库通常也有独特的使用场景和应用需求,有一定的价值。下面是一些常见的“数据库其他”: MongoDB…

    Java 2023年5月19日
    00
  • 微信小程序实现语音识别转文字功能及遇到的坑

    实现微信小程序语音识别转文字功能的核心是使用微信开发者工具提供的语音接口进行录音和识别。下面是实现这个功能的详细步骤及遇到的坑: 第一步:引入wx.getRecorderManager()对象 在小程序的页面中,在标签或者.js文件中引入wx.getRecorderManager()对象,该对象是微信小程序提供的用于录制音频的API。 示例代码: const…

    Java 2023年5月23日
    00
  • java中面向对象的概念及知识点总结

    Java中面向对象的概念及知识点总结 一、面向对象的概念 面向对象(Object-oriented,O-O)是一种软件开发思想,它主要强调将问题看作是由各种不同对象之间的交互关系构成的。 O-O 中的“对象”是指拥有属性(变量)和方法(函数)的实体。这些对象通过通信来完成特定任务。O-O 中的“类”是指一组具有相同属性和方法的对象的抽象描述。在 Java 中…

    Java 2023年5月26日
    00
  • SpringBoot spring.factories加载时机分析

    在SpringBoot中,spring.factories文件是一种特定的配置文件,用于向Spring容器中加载自定义的配置类或者自动配置组件。 什么是SpringBoot spring.factories文件 spring.factories文件位于META-INF目录下,它是SpringBoot用来实现自动配置的一个重要组件。该文件被用于对Spring加…

    Java 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部