理解java多线程中ExecutorService使用

接下来我会为你详细讲解 “理解Java多线程中ExecutorService使用”的完整攻略。

1. ExecutorService 是什么?

ExecutorService 接口是 Java 并发 API 提供的一个线程池管理器。它可以管理一个池子中的线程数量,也可以通过合理配置线程池中的参数,来提高系统的吞吐量和性能。

2. ExecutorService 线程池的种类

ExecutorService 已经有很多不同的实现类了,其中常用的有以下几种:

2.1. FixedThreadPool

FixedThreadPool(固定大小线程池)是指在初始化线程池的时候设置线程数目,线程数目不会变化。

2.2. CachedThreadPool

CachedThreadPool(缓存线程池)是指在运行的过程中,根据需要创建新的线程,当线程超过一定时间没有被使用,就自动销毁。

2.3. SingleThreadPool

SingleThreadPool(单线程池)是指只有一个核心线程,也就是线程池的最大容量为 1。通常用于这种场景:需要处理逐一处理任务,而不是并发的处理任务。

2.4. ScheduledThreadPool

ScheduledThreadPool(定时任务线程池)是指在固定时间间隔内执行定时任务线程池。

3. ExecutorService 的使用方法

首先,在使用 Runnable 或者 Callable 作为 Thread 的构造函数的时候,我们可以将这些的目标作为 向Executor提交的任务(Task)

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable");
    }
}

public class Main{
    public static void main(String args[]){
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        threadPool.execute(new MyRunnable()); // 向线程池提交任务
}

4. ExecutorService 中 submit 方法和 execute 方法的区别

submit 方法和 execute 方法都可以向线程池提交任务,但是他们还是存在一定的区别:

  • submit 方法会【返回一个 Future】,这个 Future 可以操作刚提交的 Task 的结果
public class MyCallable implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("MyCallable");
        return "result";
    }
}

public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor(); 
        Future<String> future = executorService.submit(new MyCallable());
        try {
            String result = future.get(); // 拿到 callable 的结果
            System.out.println(result); // 打印结果
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}
  • execute 方法则不会返回结果。
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable");
    }
}

public class Main {
    public static void main(String args[]){
         ExecutorService threadPool = Executors.newFixedThreadPool(5);
         threadPool.execute(new MyRunnable());
         threadPool.shutdown(); //关闭线程池
    }
}

5. ExecutorService 的关闭

当我们使用完 ExecutorService 线程池之后,需要进行关闭。

这时,我们可以使用 shutdown 方法进行关闭,如下所示。

public class Main {
    public static void main(String args[]){
         ExecutorService threadPool = Executors.newFixedThreadPool(5);
         threadPool.execute(new MyRunnable());
         threadPool.shutdown(); //关闭线程池
    }
}

6. 示例说明

6.1. 示例1:Runnable 使用 ExecutorService

下面的代码演示了 Runnable 如何使用 ExecutorService。

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

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

class MyRunnable implements Runnable {
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 正在执行 task.");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

代码说明:

  • 这里我们首先创建一个 ExecutorService 对象 threadPool,它是一个 FixedThreadPool 类型的线程池,最大线程数为 5。
  • 然后我们创建 5 个需要执行的 Task(Runable),然后分别通过 ExecutorService 来 管理它们的执行。
  • 最后通过 threadPool.shutdown() 方法等待所有的 Task 都已经执行完成,然后关闭这个ExecutorService。

输出结果如下:

pool-1-thread-1 正在执行 task.
pool-1-thread-2 正在执行 task.
pool-1-thread-3 正在执行 task.
pool-1-thread-4 正在执行 task.
pool-1-thread-5 正在执行 task.

6.2. 示例2:Callable 使用 ExecutorService

下面的代码则演示了 Callable 如何使用 ExecutorService:

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        ArrayList<Future<String>> futureList = new ArrayList<>();

        for(int i=0;i<10;i++){
            MyTask myTask = new MyTask(i);
            futureList.add(executorService.submit(myTask));
        }
        executorService.shutdown();

        for(Future<String> future:futureList){
            System.out.println(future.get());
        }
    }
}

class MyTask implements Callable<String> {
    int i;
    public MyTask(int i){
        this.i = i;
    }

    @Override
    public String call() throws Exception {
        System.out.println("正在执行一个Task: 执行第 "+i+" 个 task.");
        Thread.sleep(5000);
        return "结果:" + i;
    }
}

代码说明:

  • 这里我们首先创建一个 ExecutorService 对象,它是一个 FixedThreadPool 类型的线程池,最大线程数为 2。
  • 然后我们创建 MyTask 类,作为要执行的 10 个 Task,每个 Task 执行 5 秒。
  • 我们把所有的 Task 放入到一个 ArrayList 中,然后使用 executorService 来管理它们。
  • 使用 futureList 来存储所有 Task 的结果,最后将结果输出。

输出结果如下:

正在执行一个Task: 执行第 4 个 task.
正在执行一个Task: 执行第 5 个 task.
正在执行一个Task: 执行第 0 个 task.
正在执行一个Task: 执行第 1 个 task.
正在执行一个Task: 执行第 2 个 task.
正在执行一个Task: 执行第 3 个 task.
正在执行一个Task: 执行第 6 个 task.
正在执行一个Task: 执行第 7 个 task.
正在执行一个Task: 执行第 8 个 task.
正在执行一个Task: 执行第 9 个 task.
结果:0
结果:1
结果:2
结果:3
结果:4
结果:5
结果:6
结果:7
结果:8
结果:9

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:理解java多线程中ExecutorService使用 - Python技术站

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

相关文章

  • 一套前后台全部开源的H5商城送给大家

    博主给大家推荐一套全部开源的H5电商项目waynboot-mall。由博主在2020年开发至今,已有三年之久。那时候网上很多的H5商城项目都是半开源版本,要么没有H5前端代码,要么需要加群咨询,属实恶心。于是博主决定自己开发一套完整的移动端H5商城,包含一个管理后台、一个前台H5商城、一套后端接口。项目地址如下: H5商城前端代码:https://githu…

    Java 2023年5月6日
    00
  • 通过代理类实现java连接数据库(使用dao层操作数据)实例分享

    下面我就来详细讲解一下如何通过代理类实现Java连接数据库,并使用DAO层操作数据。 1. 环境准备 在开始操作之前,需要准备以下环境: JDK MySQL数据库 Eclipse或IntelliJ IDEA等Java开发工具 JDBC驱动包:MySQL的JDBC驱动包 2. 创建数据库 首先,需要创建一个名为“test”的数据库。可以使用MySQL命令行或可…

    Java 2023年5月19日
    00
  • JavaSwing基础之Layout布局相关知识详解

    JavaSwing是用于开发桌面应用程序的一套GUI工具包,其中Layout布局是Swing中常用的一种布局方式。此篇文章将详细讲解Layout布局的相关知识,为JavaSwing的使用提供帮助。 布局方式 Swing提供了多种布局方式,其中常见的有FlowLayout、BorderLayout、GridLayout、GridBagLayout、BoxLay…

    Java 2023年5月26日
    00
  • 基于jsp+mysql实现在线水果销售商城系统

    系统环境搭建 首先需要安装JDK和Tomcat,并进行相关配置;接着安装MySQL数据库,并在其中创建相应的数据库和表格结构。 JSP页面设计 设计网站的前端界面,包括首页、商品详情页、购物车、结算页面等,需要使用HTML、CSS、JavaScript等前端技术进行实现。 后台服务搭建 基于Java语言使用JSP技术实现后台管理服务,包括用户登录、用户注册、…

    Java 2023年6月15日
    00
  • Springboot使用Logback实现日志配置与异常记录

    Spring Boot使用Logback实现日志配置与异常记录 介绍 Spring Boot是一款轻量级的应用框架,它提供了很多有用的功能来简化应用开发流程,其中包括了日志记录功能。Logback是一个优秀的日志框架,它可以取代Java标准库的日志框架,并支持通过XML文件配置日志。在这篇教程中,我们将看到如何在Spring Boot应用中使用Logback…

    Java 2023年5月25日
    00
  • SpringBoot war包部署到Tomcat服务器

    下面我将向您介绍如何将Spring Boot的war文件部署到Tomcat服务器上。 步骤一:修改pom.xml文件 在pom.xml文件中,我们需要将spring-boot-starter-tomcat依赖改为provided,以避免在打包war包时将Tomcat运行时环境打进war包中。代码示例如下: <!–在<dependencies&g…

    Java 2023年5月19日
    00
  • java 中断线程的几种方式 interrupt()详解

    Java 中断线程的几种方式 interrupt()详解 在 Java 中,一条线程可以通过另一条线程中断,可以说是线程通信的一种方式。本文将会详细的讲解 Java 中线程中断的几种方式以及如何检测线程是否被中断。 interrupt() 方法 Java 提供了 interrupt() 方法作为一种中断线程的方式,在线程启动后,可以使用该方法将线程设置为中断…

    Java 2023年5月18日
    00
  • 浅谈Spring Security 对于静态资源的拦截与放行

    浅谈Spring Security 对于静态资源的拦截与放行 背景 在开发Web应用时,通常需要对系统中的URL资源进行访问控制,以保证系统安全。在Web开发中,Spring Security 是常见的安全框架,它提供了一系列的安全解决方案来对系统进行保护。其中一项功能就是对静态资源的拦截和放行。 Spring Security 配置 Spring Secu…

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