项目实战-NewFixedThreadPool线程池

简介: 项目实战-NewFixedThreadPool线程池

什么是线程池

       线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。

ff3c40384a0d4988b00ac8a6e4549f48.png

线程池的类型

1.CachedThreadPool

       适合使用在任务量 大但耗时少的任务。

2.FixedThreadPool

       适合使用在任务量比 较固定但耗时长的任务。

3.ScheduledThreadPool

       适合使用在执行 定时任务和具体固定周期的重复任务。

4.SingleThreadPool

       适合使用在多个任务 顺序执行的场景。

5.newWorkStealingPool

       适合使用在很耗 时的任务中。

线程池的好处

1、线程池的重用

       线程的创建和销毁的开销是巨大的,而通过线程池的重用大大减少了这些不必要的开销,当然既然少了这么多消费内存的开销,其线程执行速度也是突飞猛进的提升。

2、控制线程池的并发数

       控制线程池的并发数可以有效的避免大量的线程池争夺CPU资源而造成堵塞。

3、线程池可以对线程进行管理

       线程池可以提供定时、定期、单线程、并发数控制等功能。比如通过ScheduledThreadPool线程池来执行S秒后,每隔N秒执行一次的任务。

线程池的示例

       拿NewFixedThreadPool线程池举例。newFixedThreadPool的特点是他的核心线程数和最大线程数是一致的,并且是一个固定线程数的线程池。线程池的大小一旦达到最大值后,再有新的任务提交时则放入无界阻塞队列中,等到有线程空闲时,再从队列中取出任务继续执行。

1.Client启动类

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * @BelongsProject: demo
 * @BelongsPackage: com.wzl
 * @Author: Wuzilong
 * @Description: 线程池-多线程
 * @CreateTime: 2022-12-30 08:55
 * @Version: 1.0
 */
public class Client {
    public static void main(String[] args) {
        ExecutorService executorService= Executors.newFixedThreadPool(80);
        //构造CountDownLatch传入数量为10000,初始化的计数器大小为1000,与学生数量对应。
        List<String> number=new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            number.add( "少了" +i +"袋牛奶");
        }
        final CountDownLatch latch = new CountDownLatch(number.size());
        //计算1000个学生的学习数据
        for (int i = 0; i <number.size() ; i++) {
            //线程提交任务
            executorService.submit(new DrinkMilk(i,latch,number));
        }
        try{
            //使调用该方法的主线程处于等待状态,当倒数到0时主线程才执行。
            latch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException("XXX喝牛奶多线程处理异常",e);
        }
        //关闭线程池
        executorService.shutdown();
    }
}

newFixedThreadPool(80):80指的是线程池的固定大小,根据电脑的配置情况来启动对应的线程数

new DrinkMilk(i,latch,number):将具体业务需要用到的对象或者值通过实例化对象以构造函数的形式传到具体业务类中

CountDownLatch(number.size()):等子线程都执行完毕之后,主线程才继续执行。传入的参数要和执行的线程是一致的

2.具体业务类:实现Runnable接口,并实现了run方法

import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
 * @BelongsProject: demo
 * @BelongsPackage: com.wzl
 * @Author: Wuzilong
 * @Description: 具体业务类
 * @CreateTime: 2022-12-30 08:55
 * @Version: 1.0
 */
public class DrinkMilk implements Runnable {
    int drinkMilkNumber;
    CountDownLatch latch;
    List<String> number;
    public DrinkMilk(int drinkMilkNumber, CountDownLatch latch, List<String> number) {
        this.drinkMilkNumber=drinkMilkNumber;
        this.latch=latch;
        this.number=number;
    }
    @Override
    public void run() {
        this.business();
        latch.countDown();
    }
    private void business(){
        System.out.println("XXX喝了"+drinkMilkNumber+"袋牛奶!"+Thread.currentThread().getName());
    }
}

3.执行结果

b92e760662be4f35955baa144cf6d041.png


相关文章
|
存储 Java
在项目中使用——newFixedThreadPool线程池
在项目中使用——newFixedThreadPool线程池
339 0
|
Java
【Java 并发编程】线程池机制 ( 线程池示例 | newCachedThreadPool | newFixedThreadPool | newSingleThreadExecutor )
【Java 并发编程】线程池机制 ( 线程池示例 | newCachedThreadPool | newFixedThreadPool | newSingleThreadExecutor )
139 0
【Java 并发编程】线程池机制 ( 线程池示例 | newCachedThreadPool | newFixedThreadPool | newSingleThreadExecutor )
|
缓存 Java
【小家Java】一次Java线程池误用(newFixedThreadPool)引发的线上血案和总结(下)
【小家Java】一次Java线程池误用(newFixedThreadPool)引发的线上血案和总结(下)
|
4天前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
16 1
|
2月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
60 1
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
32 3
|
2月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
25 2
|
2月前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
41 2
|
2月前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
47 1
|
2月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
54 1