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日

相关文章

  • 基于java文件上传-原始的Servlet方式

    下面是基于Java文件上传-原始的Servlet方式的完整攻略。 准备工作 在开始前,我们需要几个准备工作: 1.安装JDK并配置环境变量2.安装Tomcat并配置环境变量3.新建一个Java Web项目 编写HTML页面 在项目的WebContent目录下新建一个html文件,编写如下代码: <html> <body> <fo…

    Java 2023年6月15日
    00
  • 结合Service层讲解DAO层的异常处理操作

    让我详细讲解一下“结合Service层讲解DAO层的异常处理操作”的攻略。 首先,我们需要理解DAO(Data Access Object)层的作用。DAO层的主要任务是实现数据的持久化操作,负责与数据库交互,为上层提供数据访问接口。在实现DAO层的过程中,异常处理也是至关重要的一部分。 DAO层的异常处理分为两种情况: SQL异常 SQL异常是指在数据库操…

    Java 2023年5月27日
    00
  • 垃圾回收的实现原理是什么?

    下面我就来详细讲解一下“垃圾回收的实现原理是什么?”的完整使用攻略。 垃圾回收的实现原理 垃圾回收是一种自动化内存管理的技术,它可以在程序运行时,自动回收不再被使用的内存,以避免内存泄漏和内存溢出等问题的发生。垃圾回收的实现原理主要分为以下几个步骤: 标记阶段:首先遍历整个堆内存,对每个对象进行标记,标记出那些是活对象,那些是死对象; 清除阶段:然后将所有死…

    Java 2023年5月11日
    00
  • Dubbo3的Spring适配原理与初始化流程源码解析

    Dubbo3的Spring适配原理与初始化流程源码解析攻略: 1. 前言 Dubbo3是阿里巴巴开发的一款高性能和轻量级的RPC框架,具有很强的扩展性和灵活性,其底层采用Netty和Java NIO技术实现。Dubbo3提供了与Spring框架无缝集成的能力,本文将深入探究Dubbo3如何与Spring框架集成,并分析Dubbo3的Spring适配原理和初始…

    Java 2023年5月31日
    00
  • java解析任意层数json字符串的方法

    关于“java解析任意层数json字符串的方法”的攻略,我会从以下几个方面进行讲解: JSON介绍 JSON解析器的选择 JSON解析实例 多层嵌套JSON解析实例 1. JSON介绍 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写。它基于JavaScript语法的子集,但在使用时可以被许多不同语言…

    Java 2023年5月26日
    00
  • 深入剖析构建JSON字符串的三种方式(推荐)

    深入剖析构建JSON字符串的三种方式(推荐) 在Web开发中,构建JSON字符串是一种常见的需求。通过JSON字符串的构建,我们可以方便地将数据从服务器传递到客户端。 在这里,我为大家介绍三种构建JSON字符串的方式。这些方式覆盖了大部分在Web开发中使用JSON字符串的常见情况。 手动构建JSON字符串 这种方式是最基础的,也最容易理解的方式。我们通过字符…

    Java 2023年5月26日
    00
  • SpringBoot日志框架如何使用

    SpringBoot日志框架如何使用 SpringBoot提供了多种日志框架,包括Logback、Log4j2、Java Util Logging等。本文将介绍如何在SpringBoot应用程序中使用Logback和Log4j2,并提供详细的配置和使用方法。 1. 使用Logback 1.1 添加依赖 在使用Logback之前,我们需要在pom.xml文件中…

    Java 2023年5月15日
    00
  • 浅谈jsp文件和HTML互相引入的乱码问题

    来讲解一下如何解决jsp文件和HTML互相引入的乱码问题。 1. 问题背景 在jsp文件中,我们经常需要嵌入html页面,即在jsp文件中引入html文件。但是在引入的过程中,经常会出现乱码的情况。 比如,在一个jsp文件中引入一个html文件: <%@ page contentType="text/html;charset=UTF-8&qu…

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