java中线程池

本文深入解析线程池的基本概念、工作原理及其在Java中的实现方式,包括四种常见线程池的创建与使用,以及它们如何提升系统性能和响应速度。

1.线程池的定义

      线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源,提高了代码执行效率。。

2.线程池的使用

在JDK的java.util.concurrent.Executors中提供了多种生成多种线程池的静态方法

  • ExecutorService newCachedThreadPool=Executors.newCachedThreadPool();
  • ExecutorService newFixedThreadPool= Executors.newFixedThreadPool(int nThreads);
  • ScheduledExecutorService newScheduledThreadPool=Executors.newScheduledThreadPool(int corePoolSize);
  •  ExecutorService newSingleThreadExecutor=Executors.newSingleThreadExecutor();

然后调用他们的execute方法即可

3.常用的线程池有哪些

  • newCachedThreadPool:创建一个可缓存的线程池,该线程池不会对线程池大小做限制,它的大小取决于操作系统(或JVM)能够创建的最大线程的大小。
  • newFixedThreadPool:创建一个大小固定的线程池,每提交一个任务,就创建一个线程,直到达到线程池的最大线程大小。
  • newScheduledThreadPool:创建一个支持定时和周期性执行任务的线程池。
  • newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

4.使用线程池的好处

  1. 降低资源消耗。通过重复利用已创建的线程,从而降低创建和销毁的消耗。
  2. 提高响应速度。当任务到达时,不需要等待线程创建,直接可以执行任务。
  3. 提高线程的可管理性。使用线程池可以实现对线程统一分配、调优和监控。

5.线程池的启动策略

    当调用execute()去添加一个任务时,线程会做以下判断

  1.  如果正在运行的线程数小于corePoolSize(核心线程数),那么马上会创建线程执行这个任务
  2. 如果正在运行的线程数大于或等于corePoolSize,那么会将这个这个任务放入队列。
  3. 如果此时队列满了,而且正在运行的线程数小于maximumPoolSize,那么还是要创建线程执行这个任务
  4. 如果此时队列满了,而且正在运行的线程数大于或等于maximumPoolSize,那么线程池会抛出异常,告诉调用者无法再接受任务了。

     

注意:(1)在这个过程中,当一个线程完成任务,它会从队列里取出下一个任务来执行

            (2)当一个线程无事可做,超过一定的时间(KeepAliveTime:线程被回收前的空闲时间)时,线程池会判断;如果当前运行的线程数大于corePoolSize,那么这个线程就会被停掉。

            (3)当线程池所有任务完成后,他最终会收缩到corePoolSize的大小。

下面对几个线程池进行逐一进行代码示例:

处理线程代码

class MyThread implements Runnable{

    private Integer index;
    public  MyThread(Integer index)
    {
        this.index=index;
    }
    @Override
    public void run() {
		System.out.println("正在执行的线程是:"+Thread.currentThread().getName());
    }
}

(1) newCachedThreadPool
创建一个可缓存线程池,应用中存在的线程数可以无限大

public class Threadpools {
    public static  void main(String[]args)
    {
        // 创建一个可缓存线程池
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        for(int index=0;index<4;index++)
        {
          newCachedThreadPool.execute(new MyThread(index));
        }
        //关闭线程池
        newCachedThreadPool.shutdown();
    }
}

运行结果:

(2) newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:

public class Threadpools {
	    public static  void main(String[]args)
	    {
	        // 创建一个固定大小的线程池
	        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
	        for(int index=0;index<4;index++)
	        {
	          newFixedThreadPool.execute(new MyThread(index));
	        }
	        //关闭线程池
	        newFixedThreadPool.shutdown();
	    }
	}

运行结果:

(3)  newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下

public class Threadpools {
    public static  void main(String[]args)
    {
        // 创建一个固定大小的线程池,支持周期性及定时任务执行。
    	ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(2);
        for(int index=0;index<4;index++)
        {
        	newScheduledThreadPool.schedule(new MyThread(index), 3,TimeUnit.SECONDS);
        }
        //关闭线程池
        newScheduledThreadPool.shutdown();
    }
}

运行结果:

延迟3秒后出现,除此之外其他执行结果与newFixedThreadPool相同

(4)newSingleThreadPool

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。

public class Threadpools {
    public static  void main(String[]args)
    {
        // 创建一个单线程的线程池
    	ExecutorService newSingleThreadPool= Executors.newSingleThreadExecutor();
        for(int index=0;index<4;index++)
        {
        	newSingleThreadPool.execute(new MyThread(index));
        }
        //关闭线程池
        newSingleThreadPool.shutdown();
    }
}
### Java 中线程池的使用方法及示例代码 Java 中的线程池主要用于管理和重用线程资源,从而提高应用程序的性能和响应速度。以下是关于线程池的具体实现方式及相关示例代码。 #### 一、线程池的核心概念 线程池的主要目的是减少每次创建新线程所带来的开销,并允许更高效地管理并发任务。核心组件包括 `Executor` 接口及其子接口 `ExecutorService`,以及具体的实现类如 `ThreadPoolExecutor` 和一些便捷工厂方法(如 `Executors.newFixedThreadPool()` 等)[^1]。 --- #### 二、常用的线程池类型及其实现 ##### 2.1 FixedThreadPool 此线程池具有固定的线程数量,超出的任务会被放入队列中等待执行。 ```java // 创建一个固定大小为3的线程池 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 5; i++) { final int taskNumber = i; fixedThreadPool.execute(() -> { System.out.println("Task " + taskNumber + " is running on thread " + Thread.currentThread().getName()); }); } fixedThreadPool.shutdown(); // 关闭线程池 ``` 这种方式适用于需要严格控制并发线程数的情况[^2]。 --- ##### 2.2 CachedThreadPool 此类线程池会根据需要动态创建新的线程,但在空闲时会回收未使用的线程。 ```java ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int taskIndex = i; cachedThreadPool.submit(() -> { try { Thread.sleep(100); // 模拟耗时操作 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("Executing Task " + taskIndex); }); } cachedThreadPool.shutdown(); ``` 适合短生命周期的小型任务场景。 --- ##### 2.3 SingleThreadExecutor 仅有一个工作线程,按顺序依次执行提交的任务。 ```java ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); singleThreadExecutor.submit(() -> System.out.println("First Task")); singleThreadExecutor.submit(() -> System.out.println("Second Task")); singleThreadExecutor.shutdown(); ``` 常用于串行化任务处理。 --- ##### 2.4 ScheduledThreadPool 能够安排命令在未来某个时刻执行,也可以周期性地重复执行某项任务。 ```java ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2); scheduledThreadPool.schedule(() -> System.out.println("Delayed Task"), 2, TimeUnit.SECONDS); scheduledThreadPool.scheduleAtFixedRate(() -> { System.out.println("Periodic Task at " + LocalDateTime.now()); }, 0, 1, TimeUnit.SECONDS); scheduledThreadPool.shutdown(); ``` 对于定时任务非常有用。 --- ##### 2.5 WorkStealingPool (JDK 1.8 新增) 利用 ForkJoinPool 技术实现的工作窃取算法,旨在最大化 CPU 利用率。 ```java ExecutorService workStealingPool = Executors.newWorkStealingPool(); IntStream.rangeClosed(1, 5).forEach(i -> { workStealingPool.submit(() -> { System.out.println("Task-" + i + " executed by " + Thread.currentThread().getName()); }); }); workStealingPool.shutdown(); ``` 推荐在高吞吐量计算密集型环境中采用。 --- #### 三、手动创建线程池 (`ThreadPoolExecutor`) 如果默认提供的几种线程池无法完全满足业务需求,则可通过 `ThreadPoolExecutor` 自定义更多细节参数。 ```java ThreadPoolExecutor customThreadPool = new ThreadPoolExecutor( 2, // 核心线程数 corePoolSize 4, // 最大线程数 maximumPoolSize 60L, // 空闲线程存活时间 keepAliveTime TimeUnit.SECONDS, // 时间单位 unit new LinkedBlockingQueue<>(100)); // 任务队列 queue customThreadPool.execute(() -> System.out.println("Custom Pool Example")); customThreadPool.shutdown(); ``` 通过调整这些参数可以灵活应对各种复杂情况。 --- ### 总结 以上分别介绍了五种典型的线程池类型及其适用范围,并提供了相应的代码片段帮助理解其基本用法。合理选用合适的线程池有助于优化系统的整体表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值