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获取json中的全部键值对实例

    下面是Java获取JSON中的全部键值对的攻略: 步骤一:导入相关包 获取JSON中的全部键值对需要用到Java中的相关包,需要在代码中进行导入,示例代码如下: import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import java.util.Iterator…

    Java 2023年5月26日
    00
  • Java数组(Array)最全汇总(中篇)

    Java数组(Array)最全汇总(中篇) 一、概述 本文讲解Java数组的相关知识点,包括定义数组、初始化、数组访问、遍历、数组长度、多维数组等。 二、定义数组 Java数组是一个存储相同类型元素的容器。数组的定义需要指定元素类型和数组大小。 使用以下语法来定义一个数组: dataType[] arrayName; //或者 dataType arrayN…

    Java 2023年5月26日
    00
  • Java操作hdfs文件系统过程

    Java操作HDFS文件系统通常需要遵循如下步骤: 连接HDFS 通过FileSystem类的静态方法get()可获取HDFS文件系统的实例: Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://localhost:9000&quo…

    Java 2023年5月19日
    00
  • java合并多个文件的实例代码

    Java合并多个文件的实例代码,可以通过以下步骤实现: 1. 获取所有待合并文件的文件名和路径 我们可以使用Java中的File类来获取指定目录下的所有文件的文件名和路径,具体实现代码如下: File dir = new File("待合并文件所在的文件夹路径"); File[] files = dir.listFiles(); for …

    Java 2023年5月20日
    00
  • jsp中session过期设置及web.xml配置学习

    下面是关于“jsp中session过期设置及web.xml配置学习”的完整攻略: 1. session过期设置 1.1 什么是session过期? 在jsp开发中,session在很多场合都扮演了非常重要的角色,他可以用来存储用户的登录状态、用户浏览过的历史页面、用户购物车等等。但是,session也会因为一些原因来使其“死亡”,也就是所谓的过期失效。 1.…

    Java 2023年6月15日
    00
  • JSP实现带查询条件的通用分页组件

    JSP 实现带查询条件的通用分页组件的完整攻略,主要分以下三个步骤: 在前端页面搭建分页组件的基本框架 在后台编写分页查询的 SQL 语句,实现数据的分页查询 前后端的数据交互和页面渲染 下面我们来详细讲解这三个步骤。 步骤一:前端页面搭建分页组件的基本框架 在前端页面,我们需要搭建一个分页组件的基本框架,包括必要的 HTML 结构和样式,以及 JavaSc…

    Java 2023年6月15日
    00
  • Java中StringBuilder类的介绍与常用方法

    关于Java中StringBuilder类的介绍与常用方法,我为你准备了以下攻略: StringBuilder类的介绍 StringBuilder是在JDK 1.5中引入的一个新类,用于代替StringBuffer。与StringBuffer类似,StringBuilder也被设计成可变的字符串类,在字符串频繁修改的情况下,使用StringBuilder比使…

    Java 2023年5月27日
    00
  • 什么是垃圾回收器?

    以下是关于垃圾回收器的完整使用攻略: 什么是垃圾回收器? 垃圾回收器是一种自动内存管理机制,用于在程序运行时自动回收不再使用的内存空间。垃圾回收器可以检测和回收不再使用的内存空间,以便其他程序或操作系统可以使用该内存空间。垃圾回收器通常用于高级编程语言中,如Java、Python等。 垃圾回收器的示例1:Java中的垃圾回收器 Java中的垃圾回收器是一种自…

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