多线程(线程池)

简介: 多线程(线程池)

线程池

池的概念意味着可以复用, 减少创建, 销毁线程的消耗

即事先把需要使用的线程创建好, 放到 “池” 中, 需要的时候从 “池” 里取, 用完再放回 池里取

这样全程只创建和销毁线程一次(只说是一次哦, 没说一次创建和销毁多少个)即可


标准库线程池的使用

public class Main{
    public static void main(String[] args) {
      // 使用工厂方法创建线程池 (工厂方法其实是为了"填构造方法的坑 ... 此处不细说了")
        ExecutorService pool = Executors.newFixedThreadPool(10); //线程池的大小设置为 10 ,即该线程池中有10个线程
        for (int i = 0; i < 1000; i++) {
            int x = i; //这里不用i, 而是再写个x. 是因为变量捕获
            pool.submit(new Runnable() { //每一次往线程池中提交一个任务, 都会使得池中空闲的一个线程来执行该任务, 任务执行完毕后, 该线程再回到线程池, 以待下次使用
                @Override
                public void run() {
                    System.out.println("hello " + x);
                }
            });
        }
    }
}

运行结果

可以看到, 打印的结果是无序的, 说明线程池中线程拿到任务后,依旧是抢占式执行, 随机调度

循环结束后,进程并未结束, 说明线程池中的线程, 都是 前台线程

Executors 创建线程池的几种方式

而 Executors 本质上是 ThreadPoolExecutor 类的封装

ThreadPoolExecutor

ThreadPoolExecutor 提供了更多的可选参数, 可进一步细化线程池行为的设定

Java 官方文档中可以查看 ThreadPoolExecutor 类的构造方法

我们来仔细研究一下构造方法的参数

corePoolSize: 核心线程数量

maximumPoolSize: 最大线程数量 (核心线程 + 临时线程)

keepAliveTime: 临时线程的最大存活时间(如果无任务运行的话)

unit: 时间的单位(时分秒 …)

workQueue: 线程池的任务队列

threadFactory: 创建线程的工厂, 参与具体的创建线程工作

handler: 拒绝策略

其中拒绝策略参数有以下几个:

拒绝策略: 如果任务队列已满, 仍往阻塞队列里添加任务, 那么将采取先选定策略来应对

ThreadPoolExecutor.AbortPolicy: 直接抛出异常

ThreadPoolExecutor.CallerRunsPolicy: 多出来的任务, 谁添加的, 谁负责执行

ThreadPoolExecutor.DiscardOldestPolicy: 丢弃最早的任务

ThreadPoolExecutor.DidcardPolicy: 丢弃最新添加的任务


手写线程池 (简单实现)

主要是依靠 BlockingQueue – 阻塞队列来实现的, 阻塞队列在我之前的博客里也手写过, 所以在此算是偷懒了

// 手写线程池

class MyThreadPool {
    private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

    // 创建含有 n 个线程的线程池 (构造方法)
    public MyThreadPool(int n) {
        for (int i = 0; i < n; i++) {
            Thread t = new Thread(() -> {
                while(true) {
                    try {
                        Runnable runnable = queue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        }
    }

    // 注册任务给线程池
    public void submit(Runnable runnbale) {
        try {
            queue.put(runnbale);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Main{
    public static void main(String[] args) {
        MyThreadPool pool = new MyThreadPool(10);
        for(int i=0;i<1000;i++) {
            int n = i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello " + n);
                }
            });
        }
    }
}

运行结果



目录
相关文章
|
4月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
195 0
|
1月前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
139 2
|
4月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
5月前
|
Java 数据挖掘 调度
Java 多线程创建零基础入门新手指南:从零开始全面学习多线程创建方法
本文从零基础角度出发,深入浅出地讲解Java多线程的创建方式。内容涵盖继承`Thread`类、实现`Runnable`接口、使用`Callable`和`Future`接口以及线程池的创建与管理等核心知识点。通过代码示例与应用场景分析,帮助读者理解每种方式的特点及适用场景,理论结合实践,轻松掌握Java多线程编程 essentials。
357 5
|
9月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
425 60
【Java并发】【线程池】带你从0-1入门线程池
|
7月前
|
Java
线程池是什么?线程池在实际工作中的应用
总的来说,线程池是一种有效的多线程处理方式,它可以提高系统的性能和稳定性。在实际工作中,我们需要根据任务的特性和系统的硬件能力来合理设置线程池的大小,以达到最佳的效果。
222 18
|
10月前
|
监控 Kubernetes Java
阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?
本文由40岁老架构师尼恩撰写,针对一线互联网企业的高频面试题“如何确定系统的最佳线程数”进行系统化梳理。文章详细介绍了线程池设计的三个核心步骤:理论预估、压测验证和监控调整,并结合实际案例(5000qps、500ms响应时间、4核8G机器)给出具体参数设置建议。此外,还提供了《尼恩Java面试宝典PDF》等资源,帮助读者提升技术能力,顺利通过大厂面试。关注【技术自由圈】公众号,回复“领电子书”获取更多学习资料。
|
9月前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
342 20
|
Prometheus 监控 Cloud Native
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
703 64
|
9月前
|
安全 Java C#
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。

热门文章

最新文章