Java并发编程中使用Executors类创建和管理线程的用法

一、介绍

在Java并发编程中,线程池是一种重要的技术。通过线程池执行任务可以大大减少资源的开销,提高程序的性能,避免线程过多导致系统资源耗尽的情况。而Executors类就是Java提供的一个专门用于创建和管理线程池的工具类。

二、使用步骤

  1. 创建线程池

创建线程池的方式有多种,其中Executors类提供了丰富的静态方法来创建不同类型的线程池。比较常用的是newFixedThreadPool()方法,可以创建指定数量的线程,如下所示:

ExecutorService executor = Executors.newFixedThreadPool(5);

这样就创建了一个固定线程池大小为5的线程池。

  1. 提交任务

线程池创建完成后,我们需要向线程池中提交任务,执行相应的操作。通过submit()方法提交一个Callable或Runnable任务,可以异步执行,如下所示:

executor.submit(new Runnable() {
    @Override
    public void run() {
        // do something
    }
});

也可以提交一个带返回值的Callable任务:

Future<String> future = executor.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {
        return "Hello";
    }
});
  1. 关闭线程池

当任务执行完成后,可以关闭线程池,释放相应的资源。可以使用shutdown()方法,如下所示:

executor.shutdown();
  1. 提交任务后获取结果

执行submit()方法后,可以获取任务的执行结果。如果是Runnable任务,没有返回值,即为null;如果是Callable任务,则可以使用Future对象获取返回值,如下所示:

Future<String> future = executor.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {
        return "Hello";
    }
});

String result = future.get();  // 获取返回结果

三、示例说明

示例一

下面我们通过一个简单的示例来说明Executors类的使用。假设有10个任务需要在5个线程池中进行计算,每个任务耗时1秒。我们可以使用Executors类创建一个固定线程池大小为5的线程池进行计算,如下所示:

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

public class ExecutorExample {
    private static final int TASK_COUNT = 10;

    public static void main(String[] args) {
        // 创建固定大小的线程池
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // 提交10个任务
        for (int i = 1; i <= TASK_COUNT; i++) {
            int taskId = i;
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 模拟任务计算
                        System.out.println("Task[" + taskId + "] start");
                        Thread.sleep(1000);
                        System.out.println("Task[" + taskId + "] end");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

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

执行结果如下所示:

Task[1] start
Task[2] start
Task[3] start
Task[4] start
Task[5] start
Task[1] end
Task[6] start
Task[2] end
Task[7] start
Task[3] end
Task[8] start
Task[4] end
Task[9] start
Task[5] end
Task[10] start
Task[6] end
Task[7] end
Task[8] end
Task[9] end
Task[10] end

可以看到,我们创建了一个固定线程池大小为5的线程池,提交10个任务进行计算,任务被线程池中的5个线程依次执行,每个任务耗时1秒。

示例二

上面的示例中,我们只是简单地提交了10个简单的任务,通过线程池执行。下面我们通过一个更复杂的示例来说明Executors类的使用。假设有一个初始值为0的计数器,需要通过多线程来并发增加其值,增加的次数是10亿次。我们可以使用Executors类创建一个固定线程池大小为10的线程池进行并发增加,如下所示:

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

public class ExecutorExample {
    private static final int TASK_COUNT = 100;
    private static final int INCREASE_COUNT = 10000000;

    public static void main(String[] args) throws InterruptedException {
        // 创建固定大小的线程池
        ExecutorService executor = Executors.newFixedThreadPool(10);

        // 使用AtomicLong保证线程安全
        AtomicLong counter = new AtomicLong(0);

        // 提交100个任务
        for (int i = 0; i < TASK_COUNT; i++) {
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    long startTime = System.currentTimeMillis();
                    for (int j = 0; j < INCREASE_COUNT; j++) {
                        counter.incrementAndGet();
                    }
                    long endTime = System.currentTimeMillis();
                    System.out.println("Thread[" + Thread.currentThread().getName() + "] cost " + (endTime - startTime) + "ms.");
                }
            });
        }

        // 等待所有任务完成
        executor.shutdown();
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

        // 输出结果
        System.out.println("Counter value: " + counter.get());
    }
}

执行结果如下所示:

Thread[pool-1-thread-2] cost 1364ms.
Thread[pool-1-thread-3] cost 1368ms.
Thread[pool-1-thread-10] cost 1371ms.
Thread[pool-1-thread-9] cost 1384ms.
Thread[pool-1-thread-7] cost 1380ms.
Thread[pool-1-thread-5] cost 1380ms.
Thread[pool-1-thread-8] cost 1386ms.
Thread[pool-1-thread-1] cost 1394ms.
Thread[pool-1-thread-6] cost 1393ms.
Thread[pool-1-thread-4] cost 1405ms.
Counter value: 1000000000

可以看到,我们创建了一个固定线程池大小为10的线程池,并提交了100个任务进行并发计算,使用AtomicLong保证线程安全,最终输出了计算结果1亿。同时输出每个线程的计算时间,可以看到所有线程都是并发执行的。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程中使用Executors类创建和管理线程的用法 - Python技术站

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

相关文章

  • golang gin 框架 异步同步 goroutine 并发操作

    为了详细讲解“golang gin 框架 异步同步 goroutine 并发操作”的完整攻略,我们将分为以下几步进行: 介绍 Golang 和 Gin 框架的概念 异步和同步的原理和区别 Goroutine 并发操作的实现 完整攻略及示例说明 1. Golang 和 Gin 框架的概念 Golang 是一种高效的编程语言,由 Google 在 2009 年发…

    多线程 2023年5月16日
    00
  • Java 实现多线程的几种方式汇总

    Java 实现多线程的几种方式汇总 在 Java 编程中使用多线程是非常常见的需求,本文将汇总几种常见的 Java 多线程实现方式,帮助读者实现多线程编程。 1. 继承Thread类 使用 Thread 类并重写 run() 方法是创建一个新线程的最简单方法。以下是创建线程的步骤: 定义 Thread 的子类并重写 run() 方法。 创建 Thread 的…

    多线程 2023年5月17日
    00
  • python线程池ThreadPoolExecutor,传单个参数和多个参数方式

    Python中的ThreadPoolExecutor是一个线程池,其中包含若干个线程,当有任务需要执行时,线程池中的线程会接收任务并执行。使用ThreadPoolExecutor可以快速、便捷地实现多线程任务的执行。 在ThreadPoolExecutor中,任务的执行可以传递不同数量的参数,无论是单个参数还是多个参数形式,都可以使用。在下面的示例中,将演示…

    多线程 2023年5月17日
    00
  • python多进程并发demo实例解析

    Python是一种强大而流行的编程语言,适用于许多不同的应用程序。在编写Python应用程序时,一种常见的技术是使用多进程并发来提高应用程序的性能。本文将详细讲解Python多进程并发的实现方法,并提供一些示例代码和解释。 什么是多进程并发 在计算机科学中,多进程并发是指在同一时间内运行多个进程,这些进程可以同时访问计算机的CPU和内存资源而不相互干扰。在P…

    多线程 2023年5月16日
    00
  • Go 并发实现协程同步的多种解决方法

    Go 并发实现协程同步的多种解决方法 在 Go 编程中,对于大量协程的并发执行,我们经常需要对它们进行同步控制,以保证协程之间的正确互动和信息传递。本文介绍 Go 实现协程同步的常用方法,包括使用 WaitGroup、channel、Mutex 等。 使用 WaitGroup 举个例子,我们可能需要同时开启多个协程进行图片下载,且需要等所有协程下载完毕才能继…

    多线程 2023年5月16日
    00
  • Python异步爬虫多线程与线程池示例详解

    对于Python异步爬虫多线程与线程池示例的攻略,我将分成以下几个部分进行讲解: 简介:异步爬虫、多线程以及线程池的概念和作用 异步爬虫指的是利用异步编程模式来实现网站数据的爬取,可以大大提升程序的性能。而多线程和线程池则是更为常见的提高网络爬虫效率的手段。 多线程:通过使用多个线程来同时执行多个任务,以达到快速完成任务的效果。Python提供了多线程模块—…

    多线程 2023年5月17日
    00
  • 详解在Java中如何创建多线程程序

    当需要处理复杂任务时,使用多线程可以提高程序的并发性以及响应速度。在Java中,创建多线程程序有两种方式:继承Thread类和实现Runnable接口。下面将会详细介绍这两种方式的创建方法: 使用Thread类创建多线程程序 创建多线程程序的第一种方式是继承Thread类并重写run()方法。run()方法包含需要在多线程中执行的代码,这些代码将在单独的线程…

    多线程 2023年5月17日
    00
  • 使用JAVA实现高并发无锁数据库操作步骤分享

    使用JAVA实现高并发无锁数据库操作可以通过以下步骤进行: 1. 选择适合的数据库 选择适合高并发的无锁数据库,如Apache Cassandra或MongoDB等。 2. 设计数据结构 通过设计合适的数据结构来支持高并发无锁操作。在Cassandra中,使用列族和列名来存储数据,这些名称可以确定唯一的行。每个行可以包含多个列族,每个列族下可能包含多个列。在…

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