掌握这五种多线程方法,提高Java代码效率

如果您的应用程序与那些能够同时处理多个任务的应用程序相比表现不佳 , 很可能是因为它是单线程的 。解决这个问题的方法之一是采用多线程技术 。
以下是一些可以考虑的方法:

  • 线程(Thread)
  • 并行流(Parallel Streams)
  • ExecutorService
  • ForkJoinPool
  • CompletableFuture
适当地使用这些方法 , 可以彻底改变您的应用程序,并推动您的职业发展 。下面我们来看看如何将您的应用程序转变为高效的多线程应用 。
掌握这五种多线程方法,提高Java代码效率

文章插图
1. 线程(Thread)第一种选择是使用线程(Thread)类 。通过这种方式,您可以直接控制线程的创建和管理 。以下是一个示例:
CustomTask 每隔50毫秒从0数到 count - 1 。
public class CustomTask implements Runnable {private final String name;private final int count;CustomTask(String name, int count) {this.name = name;this.count = count;}@Overridepublic void run() {for (int i = 0; i < count; i++) {System.out.println(name + "-" + i + " from " +Thread.currentThread().getName());try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}a、b 和 c 是该类的三个实例 。
Thread a = new Thread(new CustomTask("a", 5));Thread b = new Thread(new CustomTask("b", 10));Thread c = new Thread(new CustomTask("c", 5));请注意,b 预计计数的次数是其他实例的两倍 。您希望在 a 和 c 顺序运行的同时运行 b 。
掌握这五种多线程方法,提高Java代码效率

文章插图
您可以非常容易地实现这种行为 。
// 首先启动 a 和 b 。a.start();b.start();//a 完成后开始 c 。a.join();c.start();以下是结果:
a-0 from Thread-0b-0 from Thread-1b-1 from Thread-1a-1 from Thread-0b-2 from Thread-1a-2 from Thread-0b-3 from Thread-1a-3 from Thread-0b-4 from Thread-1a-4 from Thread-0b-5 from Thread-1c-0 from Thread-2b-6 from Thread-1c-1 from Thread-2b-7 from Thread-1c-2 from Thread-2b-8 from Thread-1c-3 from Thread-2b-9 from Thread-1c-4 from Thread-2【掌握这五种多线程方法,提高Java代码效率】a 和 b 同时开始运行,轮流输出 。a 完成后 , c 开始执行 。此外,它们全部在不同的线程中运行 。通过手动创建 Thread 实例,您可以完全控制它们 。
然而,请注意,低级线程处理也需要同步和资源管理,这可能更容易出错和复杂 。
2. 并行流(Parallel Streams)当您需要对大型集合中的所有元素应用相同、重复且独立的任务时,并行流非常有效 。
例如,图像调整大小是一个需要按顺序运行的繁重任务;当您有多个图像需要调整大小时 , 如果按顺序执行,将需要很长时间才能完成 。在这种情况下,您可以使用并行流并行调整它们的大小 , 如下所示 。
private static List<BufferedImage> resizeAll(List<BufferedImage> sourceImages,int width, int height) {return sourceImages.parallelStream().map(source -> resize(source, width, height)).toList();}这样,图像将同时调整大?。?节省了大量宝贵的时间 。
3. ExecutorService当实现不需要精确的线程控制时 , 可以考虑使用 ExecutorService 。ExecutorService 提供了更高层次的线程管理抽象,包括线程池、任务调度和资源管理 。
ExecutorService 是一个接口,它最常见的用法是线程池 。假设您有大量的异步任务堆积在一起 , 但是同时运行所有任务——每个任务占用一个线程——似乎太多了 。线程池可以通过限制最大线程数来帮助您 。
下面的示例中,我们使用 Executors.newFixedThreadPool() 实例化 ExecutorService 来使用 3 个线程运行 10 个任务 。每个任务只打印一行 。请注意,我们在之前的部分中重用了之前定义的 CustomTask 。
ExecutorService executorService = Executors.newFixedThreadPool(3);for (int i = 0; i < 10; i++) {executorService.submit(new CustomTask(String.valueOf(i), 1));}executorService.shutdown();这将打印以下结果:
0-0 from pool-1-thread-12-0 from pool-1-thread-31-0 from pool-1-thread-24-0 from pool-1-thread-33-0 from pool-1-thread-25-0 from pool-1-thread-16-0 from pool-1-thread-17-0 from pool-1-thread-38-0 from pool-1-thread-29-0 from pool-1-thread-3


推荐阅读