线程池与并发工具:让并发编程更简单、高效!

举报
喵手 发表于 2025/06/09 16:21:25 2025/06/09
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  在多线程编程中,线程的创建和销毁是非常耗费资源的,频繁地创建和销毁线程会导致性能下降。为了提高并发性能,Java 提供了线程池和其他并发工具类,这些工具能够帮助我们更高效地管理和执行线程,减少资源的浪费。今天我们将深入探讨 Executor框架与线程池Callable与Future接口CountDownLatch、CyclicBarrier等同步工具类,以及 ForkJoin框架与并行计算


一、Executor框架与线程池

Java 提供了 Executor 框架,用于管理和控制线程池。线程池能够复用线程,避免了每次任务提交时都要创建新线程的开销,从而提升了程序的性能。

1.1 Executor 框架概述

Executor 是一个接口,定义了用于执行异步任务的方法。ExecutorServiceExecutor 的子接口,它定义了更丰富的线程池管理和任务控制功能。

常见的线程池实现类包括:

  • ThreadPoolExecutor:最常用的线程池实现,能够自定义线程池的各项参数。
  • ScheduledThreadPoolExecutor:支持定时任务的线程池。
  • Executors:提供了静态方法来快速创建各种线程池。

1.2 创建线程池

通过 Executors 类的静态工厂方法,可以创建不同类型的线程池。常见的线程池类型包括:

  • newFixedThreadPool(int nThreads):创建一个固定大小的线程池。
  • newCachedThreadPool():创建一个可以根据需要创建新线程的线程池,空闲线程会被回收。
  • newSingleThreadExecutor():创建一个单线程线程池。
代码示例:使用 ExecutorService 创建线程池
import java.util.concurrent.*;

public class ExecutorExample {
    public static void main(String[] args) {
        // 创建一个固定大小的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // 提交任务给线程池
        executorService.submit(() -> {
            System.out.println("任务正在执行,线程名:" + Thread.currentThread().getName());
        });

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

  在这个例子中,我们创建了一个固定大小的线程池 executorService,并提交了一个任务。线程池管理着任务的执行和线程的复用,避免了频繁创建和销毁线程的开销。


二、Callable 与 Future 接口

在使用线程池执行任务时,Runnable 只能返回 void,它不允许任务执行的结果返回给调用者。如果我们希望任务有返回值,或者需要捕获异常,可以使用 Callable 接口和 Future 接口。

2.1 Callable 接口

CallableRunnable 类似,都是用于表示任务,但不同之处在于 Callable 允许任务执行有返回值,并且可以抛出异常。call() 方法返回任务的结果。

2.2 Future 接口

Future 是用于表示异步计算结果的接口。通过 Future 对象,我们可以检查任务是否完成,取消任务,或者获取任务的结果。

代码示例:使用 CallableFuture
import java.util.concurrent.*;

public class CallableFutureExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        // 创建一个 Callable 任务
        Callable<Integer> task = () -> {
            System.out.println("任务开始,线程名:" + Thread.currentThread().getName());
            Thread.sleep(2000); // 模拟任务执行
            return 123; // 返回结果
        };

        // 提交任务并获取 Future 对象
        Future<Integer> future = executorService.submit(task);

        // 获取任务结果
        Integer result = future.get();  // 阻塞,直到任务完成并返回结果
        System.out.println("任务执行结果:" + result);

        executorService.shutdown();
    }
}

  在这个例子中,我们创建了一个 Callable 任务,并通过 submit() 方法将其提交给线程池。future.get() 方法会阻塞并等待任务执行完毕,最终返回结果。


三、CountDownLatch、CyclicBarrier 等同步工具类

Java 提供了多种同步工具类,用于协调多线程之间的执行顺序。常见的同步工具类包括 CountDownLatchCyclicBarrier

3.1 CountDownLatch

CountDownLatch 用于使一个或多个线程等待直到在其他线程中执行的一组操作完成。在某些情况下,多个线程必须等待某些任务完成后才能继续执行。

  • await():让当前线程等待。
  • countDown():减少计数器的值,当计数器为零时,所有等待线程会被释放。
代码示例:使用 CountDownLatch
import java.util.concurrent.*;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        int taskCount = 3;
        CountDownLatch latch = new CountDownLatch(taskCount);

        // 启动多个线程
        for (int i = 0; i < taskCount; i++) {
            int taskId = i + 1;
            new Thread(() -> {
                try {
                    System.out.println("任务 " + taskId + " 正在执行...");
                    Thread.sleep(1000);  // 模拟任务执行
                    latch.countDown();  // 任务完成,计数器减1
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        latch.await();  // 等待所有任务完成
        System.out.println("所有任务完成,继续执行主线程");
    }
}

  在这个例子中,主线程通过 latch.await() 等待所有子线程执行完成。每个子线程完成任务后通过 latch.countDown() 减少计数器,直到所有子线程完成,主线程才继续执行。

3.2 CyclicBarrier

CyclicBarrier 用于让一组线程在某个公共屏障点上等待,直到所有线程都到达屏障点为止。与 CountDownLatch 不同的是,CyclicBarrier 在多次使用时会被重置。

代码示例:使用 CyclicBarrier
import java.util.concurrent.*;

public class CyclicBarrierExample {
    public static void main(String[] args) throws InterruptedException {
        int parties = 3;
        CyclicBarrier barrier = new CyclicBarrier(parties, () -> System.out.println("所有线程到达屏障点,继续执行"));

        // 启动多个线程
        for (int i = 0; i < parties; i++) {
            int threadId = i + 1;
            new Thread(() -> {
                try {
                    System.out.println("线程 " + threadId + " 到达屏障点");
                    barrier.await();  // 等待其他线程到达屏障点
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

  在这个例子中,CyclicBarrier 的每个线程都会等待其他线程到达屏障点,直到所有线程都到达,屏障才会被释放,允许所有线程继续执行。


四、ForkJoin框架与并行计算

ForkJoin 框架是 Java 7 引入的一个新框架,专门用于并行任务的分解和执行。它适用于需要分解为多个子任务的任务,像是大数据计算、图像处理、并行算法等。

4.1 ForkJoin 框架的基本概念

  • Fork:将任务分解为多个子任务。
  • Join:等待所有子任务完成,并将结果合并。

ForkJoinPoolForkJoin 框架的核心类,用于执行和管理分解后的任务。

代码示例:使用 ForkJoinPool
import java.util.concurrent.*;

public class ForkJoinExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ForkJoinPool forkJoinPool = new ForkJoinPool();

        // 定义一个递归任务
        RecursiveTask<Integer> task = new RecursiveTask<>() {
            @Override
            protected Integer compute() {
                return 1 + 2;  // 简单示例:返回 1 + 2
            }
        };

        // 提交任务并获取结果
        Future<Integer> result = forkJoinPool.submit(task);
        System.out.println("任务结果:" + result.get());  // 输出任务执行结果
    }
}

  在这个例子中,我们使用 ForkJoinPool 提交了一个递归任务,它返回了 1 + 2 的结果。ForkJoin 框架特别适合用来处理需要并行计算的任务。


总结:高效并发与线程控制

  通过使用线程池、同步工具类和 ForkJoin 框架,Java 为我们提供了强大的并发编程支持。Executor 框架帮助我们管理线程池,CallableFuture 接口使得任务可以有返回值,CountDownLatchCyclicBarrier 用于协调线程之间的同步,而 ForkJoin 框架则能高效地进行并行计算。

  掌握这些并发工具,你就能在多线程编程中更加游刃有余,构建出高效、可扩展的并发应用!

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。