四种常见线程池解析

一、线程池简介

1.1线程池概念

线程池就是多个线程的集合。使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。

1.2线程池优势

1.降低系统资源消耗。通过重用已存在的线程,降低线程创建和销毁造成的消耗;
2.提高系统响应速度。当有任务到达时,复用已存在的线程,无需等待新线程的创建便能立即执行;
3.方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成cpu过度切换(cpu切换线程是有时间成本的(需要保持当前执行线程的现场,并恢复要执行线程的现场))。
4.提供更强大的功能。延时定时线程池。

1.3线程池主要参数

1.corePoolSize(线程池基本大小):当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务,直到已创建的线程数大于或等于corePoolSize时,(除了利用提交新任务来创建和启动线程(按需构造),也可以通过 prestartCoreThread() 或 prestartAllCoreThreads() 方法来提前启动线程池中的基本线程。)

2.maximumPoolSize(线程池最大大小):线程池所允许的最大线程个数。当队列满了,且已创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。另外,对于无界队列,可忽略该参数。

3.keepAliveTime(线程存活保持时间)当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。

4.workQueue(任务队列):用于传输和保存等待执行任务的阻塞队列。

5.threadFactory(线程工厂):用于创建新线程。threadFactory创建的线程也是采用new Thread()方式,threadFactory创建的线程名都具有统一的风格:pool-m-thread-n(m为线程池的编号,n为线程池内的线程编号)。

6.handler(线程饱和策略):当线程池和队列都满了,再加入线程会执行此策略。

二、四种常见线程池

ExecutorService类
ExecutorService类由Java提供的用于管理线程池,该类的两个作用是控制线程数量和重用线程。

四种常用线程池实现如下(返回值都是ExecutorService)
1.Executors.newCacheThreadPool():可缓存线程池,先查看池中有没有以前建立的线程,如果有,就直接使用。如果没有,就建一个新的线程加入池中,缓存型池子通常用于执行一些生存期很短的异步型任务。

示例代码:

package com.channelPool.test;

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

public class NewCachedThreadPoolTest {
    public static void main(String[] args) {
        // 创建一个cached线程池
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            try {
                // sleep可明显看到没有创建新的线程,使用的线程都是以前线程池中存在的
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cachedThreadPool.execute(new Runnable() {
                public void run() {
                    // 打印正在执行的缓存线程信息
                    System.out.println(Thread.currentThread().getName()
                            + "正在被执行");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

输出结果:

pool-1-thread-1正在被执行
pool-1-thread-1正在被执行
pool-1-thread-1正在被执行
pool-1-thread-1正在被执行
pool-1-thread-1正在被执行

如果线程池无限大,执行当前任务的上一个任务已经完成则会复用上一个任务,而不是创建一个新的线程。

2.Executors.newFixedThreadPool(int n):创建一个可重用固定个数的线程池,以共享的无界队列方式来运行这些线程。

示例代码:

package com.channelPool.test;

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

public class NewFixedThreadPoolTest {

    public static void main(String[] args) {
        // 创建一个可重用固定个数的线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
        for (int i = 0; i < 9; i++) {
            fixedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        // 打印正在执行的缓存线程信息
                        System.out.println(Thread.currentThread().getName()
                                + "正在被执行");
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

输出结果:

pool-1-thread-1正在被执行
pool-1-thread-2正在被执行
pool-1-thread-3正在被执行
pool-1-thread-4正在被执行
pool-1-thread-1正在被执行
pool-1-thread-2正在被执行
pool-1-thread-3正在被执行
pool-1-thread-4正在被执行
pool-1-thread-1正在被执行

线程池的大小为4,每个任务输出打印后都会sleep2秒所以每过两秒就打印4个结果。定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。

3.Executors.newScheduledThreadPool(int n):创建一个定长线程池,支持定时及周期性任务执行。

示例代码:

package com.channelPool.test;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class NewScheduledThreadPoolTest {

    public static void main(String[] args) {
                 //创建一个定长线程池,支持定时及周期性任务执行——延迟执行
                 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
                 //延迟执行
                 //延迟1秒执行
                 scheduledThreadPool.schedule(new Runnable() {
                     public void run() {
                        System.out.println("延迟1秒执行");
                     }
                 }, 1, TimeUnit.SECONDS);
                 
                 //定期执行
                 //延迟1秒后每3秒执行一次
                 scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
                     public void run() {
                         System.out.println("延迟1秒后每3秒执行一次");
                     }
                }, 1, 3, TimeUnit.SECONDS);
             } 
}

延时执行输出结果:延迟1秒执行
定期执行输出结果:延迟1秒后每3秒执行一次

4.Executors.newSingleThreadExecutor():创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

示例代码:

package com.channelPool.test;

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

public class NewSingleThreadExecutorTest {			

	public static void main(String[] args) {		          
			//创建一个单线程化的线程池		          
			ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();	
			for (int i = 0; i < 10; i++) {		         					  				            
				 final int index = i;		             
				 singleThreadExecutor.execute(new Runnable() {		                 
				 	public void run() {		                    
				 		try {		                         
				 		//结果依次输出,相当于顺序执行各个任务	
			System.out.println(Thread.currentThread().getName()+"正在被执行,打印的值是:"+index);	
					Thread.sleep(5000);					                         					                         		                     
							} 
						catch (InterruptedException e) {
							e.printStackTrace();		                     
						}		                 
					}		             
				});		         
			}		     
		}
	}

输出结果:

pool-1-thread-1正在被执行,打印的值是:0
pool-1-thread-1正在被执行,打印的值是:1
pool-1-thread-1正在被执行,打印的值是:2
pool-1-thread-1正在被执行,打印的值是:3
pool-1-thread-1正在被执行,打印的值是:4
pool-1-thread-1正在被执行,打印的值是:5
pool-1-thread-1正在被执行,打印的值是:6
pool-1-thread-1正在被执行,打印的值是:7
pool-1-thread-1正在被执行,打印的值是:8
pool-1-thread-1正在被执行,打印的值是:9

参考链接:
[https://www.cnblogs.com/jiawen010/p/11855768.html]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值