首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用代码示例说明如何通过线程池实现Java多线程编程

用代码示例说明如何通过线程池实现Java多线程编程

原创
作者头像
啦啦啦191
发布2025-11-04 13:49:26
发布2025-11-04 13:49:26
3390
举报
文章被收录于专栏:Java开发Java开发

在Java中,线程池是管理多线程的高效方式,它通过复用线程减少频繁创建/销毁线程的开销。以下通过代码示例详细说明如何使用线程池实现多线程编程,包括线程池的创建、提交任务、获取结果及关闭线程池等核心操作。

一、线程池核心API简介

Java通过java.util.concurrent包提供线程池支持,核心类和接口:

  • ExecutorService:线程池核心接口,定义了提交任务、关闭线程池等方法。
  • Executors:工具类,提供快速创建常见线程池的静态方法(实际开发中推荐ThreadPoolExecutor自定义线程池,更灵活)。
  • ThreadPoolExecutor:线程池的核心实现类,可自定义核心线程数、最大线程数等参数。

二、线程池使用步骤(代码示例)

1. 基本使用:提交Runnable任务(无返回值)
代码语言:java
复制
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolRunnableDemo {
    public static void main(String[] args) {
        // 1. 创建线程池(这里用Executors.newFixedThreadPool创建固定大小的线程池)
        // 核心线程数为3,即同时最多运行3个线程
        ExecutorService executor = Executors.newFixedThreadPool(3);

        // 2. 提交任务(Runnable接口,无返回值)
        for (int i = 0; i < 5; i++) { // 提交5个任务
            final int taskId = i; // 任务编号
            // 提交Runnable任务
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    // 任务逻辑:打印线程名和任务ID,模拟耗时操作
                    System.out.println("线程" + Thread.currentThread().getName() 
                                       + " 执行任务" + taskId);
                    try {
                        Thread.sleep(1000); // 模拟任务耗时1秒
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        // 3. 关闭线程池(重要!否则程序会一直运行)
        // shutdown():不再接受新任务,等待已有任务执行完毕后关闭
        executor.shutdown();
    }
}

输出说明

线程池有3个核心线程,5个任务会分两批执行(前3个同时执行,1秒后执行剩余2个),输出类似:

代码语言:txt
复制
线程pool-1-thread-1 执行任务0
线程pool-1-thread-2 执行任务1
线程pool-1-thread-3 执行任务2
(1秒后)
线程pool-1-thread-1 执行任务3
线程pool-1-thread-2 执行任务4
2. 提交Callable任务(有返回值)

如果需要线程返回结果,可提交Callable任务,通过Future获取结果。

代码语言:java
复制
import java.util.ArrayList;
import java.util.List;
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 ThreadPoolCallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1. 创建线程池(单线程池,仅1个线程)
        ExecutorService executor = Executors.newSingleThreadExecutor();

        // 2. 提交Callable任务(有返回值,这里返回1~n的和)
        Callable<Integer> task = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int sum = 0;
                for (int i = 1; i <= 100; i++) {
                    sum += i;
                }
                return sum; // 返回计算结果
            }
        };

        // 提交任务并获取Future对象(用于获取结果)
        Future<Integer> future = executor.submit(task);

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

        // 4. 通过Future获取结果(get()会阻塞,直到任务完成)
        int result = future.get();
        System.out.println("1~100的和:" + result); // 输出:5050
    }
}

多任务批量获取结果示例

代码语言:java
复制
public class ThreadPoolMultiCallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 创建固定大小为2的线程池
        ExecutorService executor = Executors.newFixedThreadPool(2);

        // 存储多个Future对象
        List<Future<Integer>> futures = new ArrayList<>();

        // 提交3个任务(计算1~n的和)
        for (int i = 1; i <= 3; i++) {
            final int num = i * 100; // 分别计算1~100、1~200、1~300的和
            Future<Integer> future = executor.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int sum = 0;
                    for (int j = 1; j <= num; j++) {
                        sum += j;
                    }
                    return sum;
                }
            });
            futures.add(future);
        }

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

        // 遍历Future获取所有结果
        for (int i = 0; i < futures.size(); i++) {
            System.out.println("1~" + (i + 1) * 100 + "的和:" + futures.get(i).get());
        }
    }
}

输出

代码语言:txt
复制
1~100的和:5050
1~200的和:20100
1~300的和:45150
3. 自定义线程池(ThreadPoolExecutor

Executors创建的线程池有潜在风险(如newCachedThreadPool可能创建大量线程导致OOM),实际开发中推荐用ThreadPoolExecutor自定义参数:

代码语言:java
复制
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CustomThreadPoolDemo {
    public static void main(String[] args) {
        // 自定义线程池参数
        int corePoolSize = 2; // 核心线程数(常驻线程)
        int maximumPoolSize = 4; // 最大线程数(核心线程+临时线程)
        long keepAliveTime = 60; // 临时线程空闲时间
        TimeUnit unit = TimeUnit.SECONDS; // 时间单位
        // 任务队列(容量为2,超出的任务会创建临时线程)
        ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);

        // 创建自定义线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue
        );

        // 提交5个任务
        for (int i = 0; i < 5; i++) {
            final int taskId = i;
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程" + Thread.currentThread().getName() 
                                       + " 执行任务" + taskId);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

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

参数说明

  • 核心线程数2,任务队列容量2。提交5个任务时:
    • 前2个任务由核心线程执行;
    • 中间2个任务放入队列等待;
    • 第5个任务触发创建临时线程(最大线程数4,因此可创建2个临时线程)。

三、线程池常用方法

方法

说明

submit(Runnable)

提交无返回值的任务,返回Future<?>

submit(Callable<T>)

提交有返回值的任务,返回Future<T>

shutdown()

平缓关闭:不再接受新任务,等待现有任务完成后关闭

shutdownNow()

强制关闭:尝试中断所有任务,返回未执行的任务

isShutdown()

判断线程池是否已关闭

isTerminated()

判断所有任务是否执行完毕

四、线程池优势总结

  1. 复用线程:减少线程创建/销毁的资源消耗。
  2. 控制并发数:避免线程过多导致的系统资源耗尽。
  3. 管理任务队列:有序执行任务,避免任务丢失。
  4. 提高响应速度:核心线程常驻,无需等待线程创建即可执行任务。

通过线程池实现多线程编程是工业级开发的最佳实践,需根据业务场景合理选择线程池类型和参数。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、线程池核心API简介
  • 二、线程池使用步骤(代码示例)
    • 1. 基本使用:提交Runnable任务(无返回值)
    • 2. 提交Callable任务(有返回值)
    • 3. 自定义线程池(ThreadPoolExecutor)
  • 三、线程池常用方法
  • 四、线程池优势总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档