首页 > 编程语言 >JavaSE——多线程2:线程池详解

JavaSE——多线程2:线程池详解

时间:2024-10-28 18:45:49浏览次数:8  
标签:MyRunnable 创建 任务 线程 new JavaSE 多线程 pool1

一、线程池介绍

        线程池(Thread Pool)是一种基于多线程处理的服务器架构,它预先创建并维护一组线程,用于处理异步任务或并发请求。线程池的设计目的是减少创建和销毁线程的开销,提高系统的响应速度和吞吐量。

(一)线程池的主要核心原理

  1. 创建一个池子,池子中是空的。
  2. 提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子。下次再次提交任务时,不需要创建新的线程,直接复用已有的线程即可。
  3. 但是如果提交任务时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待。

二、线程池代码实现

实现步骤:

  1. 创建线程池
  2. 提交任务
  3. 所有的任务全部执行完毕,关闭线程池 

Excutors:线程池的工具类通过调用方法返回不同类型的线程池对象。

public static ExecutorService  newCachedThreadPool();        创建一个没有上限的线程池
public static ExecutorService  newFixedThreadPool(int nThreads);        创建有上限的线程池

(一)创建一个没有上限的线程池

public class MyThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个没有上限的线程池
        ExecutorService pool1 = Executors.newCachedThreadPool();
  
        // 提交任务
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        
        // 3.销毁线程池(一般不销毁)
//        pool1.shutdown();
    }
}

class MyRunnable implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 3; i++) {
            System.out.println(Thread.currentThread().getName() + "----" + i);
        }
    }
}

运行结果:提交一个新任务,就创建一个新的线程

(二)创建有上限的线程池

public class MyThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException {
        // 创建有上限的线程池
        ExecutorService pool1 = Executors.newFixedThreadPool(3);

        // 提交任务
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());

        // 3.销毁线程池(一般不销毁)
//        pool1.shutdown();
    }
}
class MyRunnable implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 3; i++) {
            System.out.println(Thread.currentThread().getName() + "----" + i);
        }
    }
}

运行结果:无论提交多少个新任务,只会创建指定线程数

三、自定义线程池——ThreadPoolExecutor

(一)自定义线程池的七个参数

参数参数解释参数范围
int corePoolSize核心线程数量不能小于0
int maximumPoolSize最大线程数量不能小于等于0,最大数量>=核心线程数
long keepAliveTime空闲线程最大存活空间不能小于0
TimeUnit unit时间单位用TimeUnit指定
BlockingQueue<Runnable> workQueue任务队列不能为null
ThreadFactory threadFactory创建线程工厂不能为null
RejectedExecutionHandler handler任务的拒绝策略不能为null

自定义线程池任务拒绝策略

设置核心线程数为3,最大线程数为6,队列长度为3:

        提交3个任务:此时线程池中就会创建3个线程来处理这3个任务;

        提交5个任务:此时线程池中会创建3个线程来处理3个任务,剩余的2个任务就会在任务队列中排队等待,等有了空余的线程,后面2个任务才会被执行;

        提交8个任务:此时线程池中会创建3个线程来处理3个任务,后面3个任务就会在队列中排队等待,线程池创建临时线程处理剩下2个任务;

        因此,创建临时线程的条件:核心线程都在运行,任务队列中已经排满了,才会创建临时线程处理后面的任务。

        任务在执行的时候,并不一定会按照提交的顺序来执行,先提交的任务不一定先执行。

        提交10个任务:此时提交的任务数量已经超过了最大线程数+队列长度。处理方案:线程池中会创建3个线程来处理3个任务,有3个任务在队列中等待,线程池中会创建3个临时线程处理3个任务,剩下1个任务就会触发任务的拒绝策略。

(二)最大并行数

使用代码可以获取当前电脑的最大并行数:

public class MyThreadPoolDemo2 {
    public static void main(String[] args) {
        int count = Runtime.getRuntime().availableProcessors();
        System.out.println(count); // 6
    }
}

线程池的大小:

计算比较多,读取本地文件和连接数据库的操作比较少,使用:

        CPU密集型运算:最大并行数+1

读取本地文件和连接数据库的操作比较多,使用:

        I/O密集型运算:最大并行数 * 期望CPU利用率 * (总时间(CPU计算时间+等待时间) / CPU计算时间)

标签:MyRunnable,创建,任务,线程,new,JavaSE,多线程,pool1
From: https://blog.csdn.net/Helen_1997_1997/article/details/129843128

相关文章

  • 【记录一下】lazarus多线程的用法
    网友“蓝天白云”在qq群问lazarus多线程的问题,以下代码是“啊D”给出的,但编译出错。procedureTForm1.Button2Click(Sender:TObject);beginmemo1.Text:='start...';TThread.CreateAnonymousThread(procedurevari:integer;beginSleep(1000);for......
  • 大话Java系列-并发场景下HashMap的环形链表问题,jmap检查内存状态,jstack查看线程状态,线
    文章目录童话故事故事开始发现问题解决问题代码实现1.使用普通`HashMap`导致的环形链表问题2.使用`jmap-histo`检查内存状态3.使用`jstack`查看当前线程的状态4.分析结果`jmap-histo`输出示例`jstack`输出示例5.使用ConcurrentHashMap解决问题6.使用外部加锁保......
  • Python之多线程
    一、使用threading模块的Thread类1.1介绍这是Python中最基本的创建线程的方法。通过定义一个函数,然后将这个函数作为参数传递给Thread类的构造函数来创建线程。每个线程对象代表一个独立的执行线程。1.2代码示例importthreadingimporttimedefprint_numbers():......
  • python——使用线程池实现异步返回数据
    框架flask应用场景当接收到请求,但数据处理比较耗时,希望请求过来时先返回一个响应,再慢慢处理数据,处理完成后再将结果返回给另一个地址。流程:接收到请求,立即返回响应。再处理数据,处理完成后将结果响应给预先定义的URL。importtracebackimportrequestsfromconcurrent.......
  • Java 多线程面试题
    什么是线程和进程?进程(Process)定义:进程是一个正在运行的程序的实例。每个进程都有自己的内存空间、数据栈和其他用于跟踪进程执行的辅助数据。特性:        进程之间是相互独立的,拥有各自的地址空间。        进程间通信(IPC)相对复杂,通常需要使用管道、套接......
  • 线程同步(互斥锁条件变量)
     线程同步互斥锁(互斥量)条件变量生产/消费者模型一、互斥锁C++11提供了四种互斥锁:mutex:互斥锁。timed_mutex:带超时机制的互斥锁。recursive_mutex:递归互斥锁。recursive_timed_mutex:带超时机制的递归互斥锁。包含头文件:#include<mutex>1、mutex类1)加锁lock()互斥锁......
  • 如果并发1000个请求url,通过虚拟线程应该怎么处理
    在Java中,如果要通过虚拟线程(VirtualThreads)处理1000个并发请求,能够有效提升吞吐量,同时避免传统线程池模型的线程资源开销。虚拟线程是JDK19引入的ProjectLoom的一部分,在JDK21中正式成为LTS版的稳定特性。下面是一个使用虚拟线程并发1000个请求的示例代码,并解释它的工作原理。......
  • 2024年最新互联网大厂精选 Java 面试真题集锦(JVM、多线程、MQ、MyBatis、MySQL、Redis
    前言春招,秋招,社招,我们Java程序员的面试之路,是挺难的,过了HR,还得被技术面,在去各个厂面试的时候,经常是通宵睡不着觉,头发都脱了一大把,还好最终侥幸能够入职一个独角兽公司,安稳从事喜欢的工作至今...近期也算是抽取出大部分休息的时间,为大家准备了一份通往大厂面试的小捷径,准备......
  • 虚拟线程一般应用在哪些场景
    虚拟线程(VirtualThreads)是Java21引入正式发布的特性之一,它极大简化了并发编程,特别适合高并发应用场景。与传统的操作系统线程相比,虚拟线程轻量级且数量可以大幅增加,因此在某些业务需求中具有优势。以下是常见的虚拟线程应用场景:1.高并发的IO密集型应用虚拟线程非常适合处理......
  • 虚拟线程实现Web服务器(处理HTTP请求)
    使用Java虚拟线程开发一个Web服务器可以显著提升并发能力,同时保持代码简洁。在这个示例中,我们将使用Java21的虚拟线程实现一个简单的HTTPWeb服务器,逐步解释每个部分的代码。实现目标通过虚拟线程处理HTTP请求。创建一个简单的Web服务器来响应客户端请求。适配IO......