Java-线程池

2023-12-20 09:49:29


Java线程池是一种用于优化线程管理的技术,可以避免由于创建和销毁线程带来的开销,提高应用程序的性能和响应速度。Java线程池主要有四种类型,分别是固定线程池、可缓存线程池、定时线程池和单一线程池。下面将分别介绍这四种线程池并给出相应的实例代码。
Java线程池是Java中的一个重要概念,它是一种用于管理和复用线程的机制。在Java应用程序中,线程池可以提高程序的性能,减少线程的创建和销毁次数,降低线程的开销,提高系统的响应速度。

Java线程池的基本原理是将一组线程放入一个线程池中,当需要执行任务时,从线程池中取出一个空闲的线程来执行任务,执行完任务后,线程不会立即销毁,而是返回线程池中等待下一次任务的到来。这样可以避免频繁地创建和销毁线程,从而提高程序的效率。

线程池的参数

Java线程池的实现方式有多种,最常见的是使用Java标准库中的ThreadPoolExecutor类。ThreadPoolExecutor类提供了一组灵活的参数,可以根据应用程序的需要来配置线程池的大小、线程的生命周期、任务队列的大小、拒绝策略等参数。
在这里插入图片描述

1.corePoolSize:线程池中用来工作的核心线程数量。
2.maximumPoolSize:最大线程数,线程池允许创建的最大线程数。
3.keepAliveTime:超出 corePoolSize 后创建的线程存活时间或者是所有线程最大存活时间,取决于配置。
4.unit:keepAliveTime 的时间单位。
5.workQueue:任务队列,是一个阻塞队列,当线程数达到核心线程数后,会将任务存储在阻塞队列中。
6.threadFactory :线程池内部创建线程所用的工厂。
7.handler:拒绝策略;当队列已满并且线程数量达到最大线程数量时,会调用该方法处理任务。

线程池的状态

线程池内部有 5 个常量来代表线程池的五种状态

private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;

在这里插入图片描述

线程池的运行原理

在这里插入图片描述

  1. 创建线程池,这时没有创建线程(懒惰),等待提交过来的任务请求,调用 execute 方法才会创建线程

  2. 当调用 execute() 方法添加一个请求任务时,线程池会做如下判断:

    • 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务
    • 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列
    • 如果这时队列满了且正在运行的线程数量还小于 maximumPoolSize,那么会创建非核心线程立刻运行这个任务,对于阻塞队列中的任务不公平。这是因为创建每个 Worker(线程)对象会绑定一个初始任务,启动 Worker 时会优先执行
    • 如果队列满了且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会启动饱和拒绝策略来执行
  3. 当一个线程完成任务时,会从队列中取下一个任务来执行

  4. 当一个线程空闲超过一定的时间(keepAliveTime)时,线程池会判断:如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉,所以线程池的所有任务完成后最终会收缩到 corePoolSize 大小

线程池的优缺点

主要优点包括:

  1. 提高程序的性能:线程池可以复用线程,减少线程的创建和销毁次数,降低线程的开销,从而提高程序的性能。

  2. 控制线程的数量:线程池可以限制线程的数量,避免线程数量过多导致系统崩溃或运行缓慢。

  3. 提高系统的响应速度:线程池可以提高系统的响应速度,当有任务到来时,可以立即执行任务,不需要等待线程的创建和启动。

  4. 简化编程:使用线程池可以简化编程,开发人员不需要手动创建和管理线程,只需要把任务提交给线程池即可。

主要缺点包括:

  1. 需要合理配置参数:线程池的性能和效果受到参数的影响,需要合理配置参数才能达到最佳效果。

  2. 可能会导致死锁:线程池中的任务可能会互相等待,导致死锁的发生。

  3. 可能会导致资源竞争:线程池中的线程可能会争夺共享资源,导致资源竞争的发生。

  4. 可能会影响程序的可伸缩性:线程池的大小和任务队列的大小可能会影响程序的可伸缩性,需要合理配置才能达到最佳效果。

线程池类型

1. 固定线程池(FixedThreadPool)

固定线程池是一种创建后不会自动关闭的线程池,可以在需要时向其中添加或删除线程。它的核心线程数在创建时指定,并在整个生命周期内保持不变。

实例代码:

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public class FixedThreadPoolExample {
    public static void main(String[] args) {
        int corePoolSize = 5; // 核心线程数
        int maximumPoolSize = 10; // 最大线程数
        long keepAliveTime = 60L; // 空闲线程等待任务的最长时间(单位:秒)
        ExecutorService executorService = Executors.newFixedThreadPool(corePoolSize);
        for (int i = 0; i < 15; i++) {
            Runnable worker = new WorkerThread("" + i);
            executorService.execute(worker);
        }
        executorService.shutdown(); // 关闭线程池,但不立即关闭已提交的任务
    }
}

2. 可缓存线程池(CachedThreadPool)

可缓存线程池是一种可以根据需要自动创建和关闭线程的线程池,它的线程数可以动态调整。当线程池中的线程空闲一段时间后,会自动关闭。当有新任务提交时,如果线程池中的线程数已经关闭,会自动创建新的线程。

实例代码:

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public class CachedThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 15; i++) {
            Runnable worker = new WorkerThread("" + i);
            executorService.execute(worker);
        }
        executorService.shutdown(); // 关闭线程池,但不立即关闭已提交的任务
    }
}

3. 定时线程池(ScheduledThreadPool)

定时线程池是一种可以在指定时间间隔内定时执行任务的线程池,它的核心线程数可以动态调整。它与可缓存线程池类似,但定时线程池可以指定任务的执行时间间隔,而可缓存线程池只能等待任务队列中的任务到达。

实例代码:

import java.util.concurrent.Executors;  
import java.util.concurrent.ScheduledExecutorService;  
import java.util.concurrent.TimeUnit;  
  
public class ScheduledThreadPoolExample {  
    public static void main(String[] args) {  
        // 创建一个定时线程池  
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);  
          
        // 提交任务到线程池,指定任务的执行时间间隔  
        executor.scheduleAtFixedRate(() -> {  
            System.out.println("Task is running on thread " + Thread.currentThread().getName());  
        }, 0, 2, TimeUnit.SECONDS);  
          
        // 关闭线程池  
        executor.shutdown();  
    }  
}

4.单线程线程池

单线程线程池只有一个核心线程,所有任务都会在这个核心线程上执行。当任务队列满了之后,如果核心线程已经执行完任务,则会创建新的非核心线程来执行任务。

实例代码:

import java.util.concurrent.Executors;  
import java.util.concurrent.ExecutorService;  
  
public class SingleThreadExecutorExample {  
    public static void main(String[] args) {  
        // 创建一个单线程的线程池  
        ExecutorService executor = Executors.newSingleThreadExecutor();  
          
        // 提交任务到线程池  
        for (int i = 1; i <= 5; i++) {  
            int taskId = i;  
            executor.submit(() -> {  
                System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());  
            });  
        }  
          
        // 关闭线程池  
        executor.shutdown();  
    }  
}

5.自定义线程池

除了以上四种常见的线程池类型之外,我们还可以根据自己的需求自定义线程池。下面是一个自定义线程池的示例代码:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class CustomThreadPool {
    private BlockingQueue<Runnable> taskQueue;
    private Thread[] workers;

    public CustomThreadPool(int numThreads) {
        taskQueue = new LinkedBlockingQueue<>();
        workers = new Thread[numThreads];

        for (int i = 0; i < numThreads; i++) {
            workers[i] = new Thread(new Worker());
            workers[i].start();
        }
    }

    public void execute(Runnable task) {
        try {
            taskQueue.put(task);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    private class Worker implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    Runnable task = taskQueue.take();
                    task.run();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}
 

文章来源:https://blog.csdn.net/aqiuisme/article/details/135093598
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。