iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java线程池由浅入深掌握到精通
  • 965
分享到

Java线程池由浅入深掌握到精通

2024-04-02 19:04:59 965人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录1.为什么使用线程池?2.线程池的好处:3.线程池使用的场合4.创建和停止线程5.停止线程池的方法6.暂停和恢复线程池1.为什么使用线程池? 反复创建线程开销大,可以复用线程池

1.为什么使用线程池?

反复创建线程开销大,可以复用线程池
过多的线程会占用太多的内存

解决以上问题的方法:

  • 用少量的线程,避免内存占用过多
  • 让这部分线程都保持工作,且反复执行任务,避免生命周期的损耗

2.线程池的好处:

加快响应速度,提高用户体验
合理利用CPU内存
统一管理

3.线程池使用的场合

服务器接受大量请求时,使用线程池技术是非常合适的,它可以大大减少线程的创建和销毁次数,提高服务器的工作效率。在实际开发中,如果创建5个以上 的线程,那么就可以使用线程池来管理线程。

4.创建和停止线程

线程池构造方法的参数?
线程池应该手动创建和自动创建那个更好?
线程池里的线程数量设置未多少合适?
停止线程的正确方法?

线程池构造函数的参数:

线程池构造函数的参数

corePoolSize: 核心线程数
线程池在完成初始化后,默认情况下,线程池中并没有任何线程,会等到有任务到来时再去创建新的线程去执行任务。
maxPoolSize:在核心线程的基础上,额外增加的线程数的上限。

在这里插入图片描述

根据图可知添加线程的规则:

1.如果线程数小于corePoolSize,即使其他工作线程处于空闲状态,也会创建一个新线程来运行任务。
2.如果线程数等于或大于corePoolSize但少于maximumPoolSize,则将任务放入队列。
3.如果线程池已满,并且线程数小于maxPoolSize,则创建一个新线程来运行任务。
4.如果队列已满,并且线程数大于或等于maxPoolSzie,则参数拒绝该任务。

添加线程规则

添加线程判断顺序:corePoolSize——workQueue——maxPoolSize

比如线程池的核心线程是5个,最大线程池大小为10个,队列为50个。
则线程池的请求最多会创建5个,然后任务将被添加到队列中,直到达到50。队列已满时,将创建最新的线程maxPoolSize,最多达到10个,如果再来任务就直接拒绝。

keepAliveTime:如果线程池当前的线程数多于corePoolSize,那么如果多余的线程空闲时间超过keepAliveTime,那么就会终止。

ThreadFactory:
默认使用Executors.defaultThreadFactory()
创建出来的线程都在同一个线程组。
如果自己指定ThreadFactory,那么就可以改变线程名、线程组、优先级、是否是守护线程等等。

常见的3中队列类型:
直接交接:SynchronousQueue
无界队列:LinkedBlockingQueue
有界队列:ArrayBlockingQueue

线程池应该手动创建和自动创建那个更好?

手动创建好,因为这样可以明确线程池的运行规则和避开资源浪费的风险。

  • newFixedThreadPool:容易造成大量内存占用,可能导致DOM
    
    public class FixedThreadPoolTest  {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(4);
            for (int i = 0; i < 500; i++) {
                executorService.execute(new Task());
            }
        }
    }
    class Task implements Runnable{
    
        @Override
        public void run() {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    }
    
  • newSingleThreadExecutor:当请求堆积的时候,可能会占用大量内存。
    
    //演示FixedThreadPool出错
    public class FixedThreadPoolOOM {
        private static ExecutorService executorService = Executors.newFixedThreadPool(1);
    
        public static void main(String[] args) {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                executorService.execute(new SubThread());
            }
        }
    }
    class SubThread implements Runnable{
    
        @Override
        public void run() {
            try {
                Thread.sleep(10000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
  • newCachedThreadPool:弊端在于第二个参数maximumPoolSize被设置为了Integer.MAX_VALUE,这可能会创建数量非常多的线程,甚至导致DOM
  • newScheduledThreadPool:原因和newCachedThreadPool一样

常见的线程池:

FixedThreadPool

在这里插入图片描述

CachedThreadPool:可缓存线程池,具有自动回收多余线程的功能

在这里插入图片描述

ScheduledThreadPool:支持定时及周期性任务执行的线程池
SingleThreadExecutor:单线程的线程池只会用唯一的工作线程来执行任务
原理和FixedThreadPool一样,但是线程数量被设为1

四种线程池的构造方法的参数:

在这里插入图片描述

阻塞队列分析:

在这里插入图片描述

5.停止线程池的方法

  • shutdown:只是将线程池的状态设置为 shutdown 状态,但任务并没有中断,还是会继续执行下去。此时线程池不会接受新的任务,只是将原有的任务执行结束。
  • shutdownNow:将线程池的状态设置为STOP,正在执行的任务会停止,没被执行的任务会被返回。
  • isshutdown:当调用shutdown()或shutdownNow()方法后返回为true,否则返回为false。
  • isTerminated:线程任务全部执行完返回true
  • awaitTerminated:有两个参数,第一个是long类型的数值,第二个是时间类型TimeUnit,用于设置阻塞时间。它是一个阻塞的方法,若线程池一直运行则会一直阻塞,直到线程池关闭返回true,或阻塞时间超过你设置的这个时间,则返回false。此方法必须放在shutdown()方法之后,否则一直在阻塞,或超过设置的阻塞时间返回false。

//演示关闭线程池
public class ShutDown {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 500; i++) {
            executorService.execute(new ShutDownTask());
        }
        Thread.sleep(1500);
//        executorService.shutdown();
//        System.out.println(executorService.isShutdown());
        executorService.awaitTermination(3L, TimeUnit.SECONDS);
    }
}
class ShutDownTask implements Runnable{

    @Override
    public void run() {
        try {
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

6.暂停和恢复线程池


//暂停线程池
 pauseAbleThreadPool.pause();
 //恢复线程池
 pauseAbleThreadPool.resume();

代码实现:


//演示每个任务执行前后放钩子函数
public class PauseAbleThreadPool extends ThreadPoolExecutor {
    private final ReentrantLock lock = new ReentrantLock();
    private Condition unpaused = lock.newCondition();
    private boolean isPaused;

    public PauseAbleThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public PauseAbleThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public PauseAbleThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public PauseAbleThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        lock.lock();
        try {
            while (isPaused) {
                unpaused.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private void pause() {
        lock.lock();
        try {
            isPaused = true;
        } finally {
            lock.unlock();
        }
    }

    public void resume() {
        lock.lock();
        try {
            isPaused = false;
            unpaused.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        PauseAbleThreadPool pauseAbleThreadPool = new PauseAbleThreadPool(10, 20, 10l, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("我被执行");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 10000; i++) {
            pauseAbleThreadPool.execute(runnable);
        }
        Thread.sleep(1500);
        pauseAbleThreadPool.pause();
        System.out.println("线程池被暂停了");
        Thread.sleep(1500);
        pauseAbleThreadPool.resume();
        System.out.println("线程池被恢复了");

    }
}

实现原理及源码分析
线程池的组成部分:

  • 线程池管理器
  • 工作线程
  • 任务队列
  • 任务接口(Task)

在这里插入图片描述

到此这篇关于Java线程池由浅入深掌握到精通的文章就介绍到这了,更多相关Java 线程池内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java线程池由浅入深掌握到精通

本文链接: https://www.lsjlt.com/news/137282.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java线程池由浅入深掌握到精通
    目录1.为什么使用线程池?2.线程池的好处:3.线程池使用的场合4.创建和停止线程5.停止线程池的方法6.暂停和恢复线程池1.为什么使用线程池? 反复创建线程开销大,可以复用线程池 ...
    99+
    2022-11-12
  • Java由浅入深带你掌握图的遍历
    目录1.图的遍历2.深度优先遍历3.利用DFS判断有向图是否存在环4.广度优先遍历1.图的遍历 从图中某一顶点出发访问图中其余顶点,且每个顶点仅被访问一次 图的遍历有两种深度优先遍历...
    99+
    2022-11-13
  • Java由浅入深带你精通继承super
    目录什么是继承背景super关键字protected 关键字final 关键字什么是继承 面向对象的特征: 封装:不必要公开的数据成员和方法,使用private关键字进行修饰。意义:...
    99+
    2022-11-13
  • 由浅入深快速掌握Java 数组的使用
    目录1.数组定义格式1.1 数组概述1.2 什么是数组1.3 数组的定义格式:2.数组初始化之动态初始化2.1 数组初始化概述2.2 数组初始化方法3.数组元素访问3.1 数组元素访...
    99+
    2022-11-13
  • 深入浅析Java中线程池的原理
    这篇文章将为大家详细讲解有关深入浅析Java中线程池的原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。ThreadPoolExecutor简介ThreadPoolExecutor是线程池类...
    99+
    2023-05-31
    java ava 线程池
  • Java教程:从入门到精通,掌握对象容器的诀窍!
    Java是一种广泛使用的编程语言,由于其简单易学、可移植性好、高效可靠等特点,深受广大开发者的喜爱。在Java编程中,对象容器是非常重要的一部分。本文将从入门到精通,介绍Java中对象容器的相关知识,并演示一些常用的代码。 一、什么是对象...
    99+
    2023-08-01
    教程 对象 容器
  • Java 容器框架教程:从入门到精通,一步步带你掌握!
    Java 是一门流行的编程语言,其容器框架是 Java 编程中最常用的工具之一。Java 容器框架提供了一组接口和类,可以存储和操作对象集合。这些容器包括 List、Set、Map 等。本教程将从 Java 容器框架的基础开始,一步步带你...
    99+
    2023-10-19
    容器 框架 教程
  • 从入门到精通,掌握Bash编程中的响应式技巧!
    Bash是一种非常强大的编程语言,可以帮助你在Linux系统中自动化许多任务。不仅如此,Bash还可以通过响应式编程技巧实现更高效的编程。在这篇文章中,我们将从入门到精通掌握Bash编程中的响应式技巧。 一、Bash的基础语法 在学习Bas...
    99+
    2023-08-08
    编程算法 bash 响应
  • 从入门到精通:掌握 PHP Windows 异步编程框架的技巧
    在如今的互联网时代,PHP是非常流行的一种编程语言,尤其是在Web开发方面,PHP的应用非常广泛。而在PHP的开发过程中,异步编程框架是一个非常重要的技术,可以大大提高程序的性能和效率。本文将从入门到精通的角度,为大家介绍掌握PHP Win...
    99+
    2023-08-16
    windows 异步编程 框架
  • PHP 函数 API 教程:从入门到精通,轻松掌握使用技巧!
    PHP 是一种广泛使用的开源服务器端脚本语言,用于 Web 开发和构建动态网站。PHP 的强大之处之一就是其函数库。PHP 函数库提供了大量的内置函数,可以轻松地完成许多常见的任务。在本教程中,我们将介绍 PHP 函数 API,并从入门到...
    99+
    2023-11-06
    函数 api 教程
  • Java深入浅出讲解多线程的概念到使用
    目录1.线程的几个相关概念2.线程的状态与生命周期3.线程的优先级与调度4.Java中多线程的创建4.1继承Thread类创建线程4.2实现Runnable接口创建线程5.多线程的同...
    99+
    2022-11-13
  • java多线程从入门到精通看这篇就够了
    目录一.认识线程及线程的创建1.线程的概念2.线程的特性3.线程的创建方式<1>继承Thread类<2>实现Runnable接口<3>实现Call...
    99+
    2022-11-12
  • 深入了解Java线程池:从设计思想到源码解读
    目录为什么需要线程池线程池设计思路线程池的工作机制线程池的参数及使用线程池的状态提交任务任务队列线程工厂拒绝策略关闭线程池Executors 静态工厂合理地配置线程池线程池的监控源码...
    99+
    2022-11-12
  • 从入门到精通,这份 PHP 数组学习笔记教程能让你轻松掌握!
    作为一门流行的编程语言,PHP 在 Web 开发中扮演着重要的角色。在 PHP 中,数组是一种非常重要的数据类型,经常被用于存储和操作数据。本文将深入讲解 PHP 数组的相关知识,从入门到精通。 一、什么是 PHP 数组? PHP 数组是...
    99+
    2023-08-07
    数组 学习笔记 教程
  • 每日六道java新手入门面试题,通往自由的道路--线程池
    目录1. 你知道线程池吗?为什么需要使用线程池?小结:2. 你知道有多少种创建线程池的方式3. 线程池的五种状态你有了解吗?4. 你知道ThreadPoolExecutor的构造方法...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作