线程池如何创建线程_创建线程池的七个参数

线程池如何创建线程_创建线程池的七个参数Executors如何创建线程池?Executors类是从JDK1.5开始就新增的线程池创建的静态工厂类,它就是创建线程池的,但是很多的大厂已经不建议使用该类去创建线程池。原因在于,该类创建的很多线程池的内部使用了无界任务队列,在并发量很大的情况下会导致JVM抛出OutOfMemoryError,直接让JVM崩溃,影响严重。但是Executors类究竟是如何使用…


Jetbrains全系列IDE稳定放心使用

Executors如何创建线程池?

Executors 类是从 JDK 1.5 开始就新增的线程池创建的静态工厂类,它就是创建线程池的,但是很多的大厂已经不建议使用该类去创建线程池。原因在于,该类创建的很多线程池的内部使用了无界任务队列,在并发量很大的情况下会导致 JVM 抛出 OutOfMemoryError,直接让 JVM 崩溃,影响严重。

 

但是 Executors 类究竟是如何使用的?

1. newFixedThreadPool,创建定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程。

package constxiong.concurrency.a011;

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

/**
 * 测试创建定长线程池
 * @author ConstXiong
 */
public class TestNewFixedThreadPool {

	public static void main(String[] args) {
		//创建工作线程数为 3 的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
		ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
		//提交 6 个任务
		for (int i = 0; i < 6; i++) {
			final int index = i;
			fixedThreadPool.execute(() -> {
				try {
					//休眠 3 秒
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + " index:" + index);
			});
		}
		
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("4秒后...");
		
		//关闭线程池后,已提交的任务仍然会执行完
		fixedThreadPool.shutdown();
	}
	
}

打印结果:

pool-1-thread-2 index:1
pool-1-thread-3 index:2
pool-1-thread-1 index:0
4秒后...
pool-1-thread-1 index:4
pool-1-thread-3 index:5
pool-1-thread-2 index:3

 

2. newCachedThreadPool,创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制。

package constxiong.concurrency.a011;

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

/**
 * 测试创建可缓存的线程池
 * @author ConstXiong
 */
public class TestNewCachedThreadPool {
	
	public static void main(String[] args) {
		//创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制
		ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

		for (int i = 0; i < 6; i++) {
			final int index = i;
			cachedThreadPool.execute(() -> {
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + " index:" + index);
			});
		}
		
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("4秒后...");
		
		cachedThreadPool.shutdown();
		
	}
	
}

打印结果可以看出,创建的线程数与任务数相等

pool-1-thread-1 index:0
pool-1-thread-3 index:2
pool-1-thread-6 index:5
pool-1-thread-4 index:3
pool-1-thread-5 index:4
pool-1-thread-2 index:1
4秒后...

 

3. newScheduledThreadPool,创建定长线程池,可执行周期性的任务。

package constxiong.concurrency.a011;

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

/**
 * 测试创建定长线程池,可执行周期性的任务
 * @author ConstXiong
 */
public class TestNewScheduledThreadPool {

	public static void main(String[] args) {
		//创建定长线程池,可执行周期性的任务
		ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
		
		for (int i = 0; i < 3; i++) {
			final int index = i;
			//scheduleWithFixedDelay 固定的延迟时间执行任务; scheduleAtFixedRate 固定的频率执行任务
			scheduledThreadPool.scheduleWithFixedDelay(() -> {
					System.out.println(Thread.currentThread().getName() + " index:" + index);
			}, 0, 3, TimeUnit.SECONDS);
		}
		
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("4秒后...");
		
		scheduledThreadPool.shutdown();

	}
}

打印结果:

pool-1-thread-1 index:0
pool-1-thread-3 index:2
pool-1-thread-2 index:1
pool-1-thread-1 index:0
pool-1-thread-2 index:1
pool-1-thread-3 index:2
4秒后...

 

4. newSingleThreadExecutor,创建单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行。

package constxiong.concurrency.a011;

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

/**
 * 测试单线程的线程池
 * @author ConstXiong
 */
public class TestNewSingleThreadExecutor {
	
	public static void main(String[] args) {
		//单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行
		ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
		
		//提交 3 个任务
		for (int i = 0; i < 3; i++) {
			final int index = i;
			singleThreadPool.execute(() -> {
				
				//执行第二个任务时,报错,测试线程池会创建新的线程执行任务三
				if (index == 1) {
					throw new RuntimeException("线程执行出现异常");
				}
				
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + " index:" + index);
			});
		}
		
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("4秒后...");
		
		singleThreadPool.shutdown();
	}

}

打印结果可以看出,即使任务出现了异常,线程池还是会自动补充一个线程继续执行下面的任务

pool-1-thread-1 index:0
Exception in thread "pool-1-thread-1" 
java.lang.RuntimeException: 线程执行出现异常
	at constxiong.concurrency.a011.TestNewSingleThreadExecutor.lambda$0(TestNewSingleThreadExecutor.java:21)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
4秒后...
pool-1-thread-2 index:2

 

5. newSingleThreadScheduledExecutor,创建单线程可执行周期性任务的线程池。

package constxiong.concurrency.a011;

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

/**
 * 测试单线程可执行周期性任务的线程池
 * @author ConstXiong
 */
public class TestNewSingleThreadScheduledExecutor {

	public static void main(String[] args) {
		//创建单线程可执行周期性任务的线程池
		ScheduledExecutorService singleScheduledThreadPool = Executors.newSingleThreadScheduledExecutor();
		
		//提交 3 个固定频率执行的任务
		for (int i = 0; i < 3; i++) {
			final int index = i;
			//scheduleWithFixedDelay 固定的延迟时间执行任务; scheduleAtFixedRate 固定的频率执行任务
			singleScheduledThreadPool.scheduleAtFixedRate(() -> {
				System.out.println(Thread.currentThread().getName() + " index:" + index);
			}, 0, 3, TimeUnit.SECONDS);
		}
		
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("4秒后...");
		
		singleScheduledThreadPool.shutdown();
	}
	
}

打印机结果可以看出 0-2 任务都被执行了 2 个周期

pool-1-thread-1 index:0
pool-1-thread-1 index:1
pool-1-thread-1 index:2
pool-1-thread-1 index:0
pool-1-thread-1 index:1
pool-1-thread-1 index:2
4秒后...

 

6. newWorkStealingPool,创建任务可窃取线程池,空闲线程可以窃取其他任务队列的任务,不保证执行顺序,适合任务耗时差异较大。

package constxiong.concurrency.a011;

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

/**
 * 测试可任务窃取线程池
 * @author ConstXiong
 */
public class TestNewWorkStealingPool {

	public static void main(String[] args) {
		//创建 4个工作线程的 任务可窃取线程池,如果不设置并行数,默认取 CPU 总核数
		ExecutorService workStealingThreadPool = Executors.newWorkStealingPool(4);
		
		for (int i = 0; i < 10; i++) {
			final int index = i;
			workStealingThreadPool.execute(() -> {
				try {
					//模拟任务执行时间为 任务编号为0 1 2 的执行时间需要 3秒;其余任务200 毫秒,导致任务时间差异较大
					if (index <= 2) {
						Thread.sleep(3000);
					} else {
						Thread.sleep(200);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + " index:" + index);
			});
		}
		
		try {
			Thread.sleep(10000);//休眠 10 秒
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("10秒后...");
	}
	
}

打印结果可以看出,线程 ForkJoinPool-1-worker-0 把3-9的任务都执行完

ForkJoinPool-1-worker-0 index:3
ForkJoinPool-1-worker-0 index:4
ForkJoinPool-1-worker-0 index:5
ForkJoinPool-1-worker-0 index:6
ForkJoinPool-1-worker-0 index:7
ForkJoinPool-1-worker-0 index:8
ForkJoinPool-1-worker-0 index:9
ForkJoinPool-1-worker-1 index:0
ForkJoinPool-1-worker-3 index:2
ForkJoinPool-1-worker-2 index:1
10秒后...

 


【Java面试题与答案】整理推荐

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/188760.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 适配器的作用计算机网络,网络适配器的作用

    适配器的作用计算机网络,网络适配器的作用网络适配器是计算机用来联网的一种设备,也就是网卡。一般这种设备就在主板的插槽中插着,它的工作原理就是通过网络介质来传输一些数据,并转为其他的格式,使这种格式能够被其他的设备所识别。网络适配器的技术参数有很多,例如带宽、电气接口方式等。网络适配器又称网卡或网络接口卡(NIC),英文名NetworkInterfaceCard。它是使计算机联网的设备。平常所说的网卡就是将PC机和LAN连接的网络适配器。…

    2022年6月1日
  • 软件测试流程详解「建议收藏」

    软件测试流程详解「建议收藏」1.软件测试的定义:使用人工或自动手段,来运行或测试某个系统的过程。其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别。百度百科定义:软件测试(英语:SoftwareTesting),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出间的审核或者比较过程。软件测试的经典定义是:在规定的条件下对程序进行操作,以发现程序错…

    2022年6月7日
  • format python保留小数点后几位_python四舍五入保留两位小数

    format python保留小数点后几位_python四舍五入保留两位小数print(“{:.2f}”.format(3.1415926))传送门

    2022年8月11日
  • list转为map

    list转为maplist转为map

    2022年4月23日
  • 用matlab绘制二元函数图像_心形函数表达式

    用matlab绘制二元函数图像_心形函数表达式文章目录Matlab二元函数图像绘制plot3函数的基本用法fplot3函数基本用法进阶用法绘制二元函数图像Matlab二元函数图像绘制在讲二元函数图像绘制之前,先讲解plot3与fplot3的实际用法,之后再讲解二元函数图像绘制,有需要的同学可直接跳转查看。plot3函数的基本用法本节通过循序渐进的方法,先介绍简单的plot3用法,接着再一步一步进阶难度,并且在代码中给出每块代码的功能以及使用方法,以帮助大家更快的学习使用。实例1:绘制三维直线%给定x、y、z的数值x=[1,2,3];

    2022年9月7日
  • 文件的三种打开方式

    文件的三种打开方式文件打开的三种方式文件操作的基础模式有三种(默认的操作为r模式):r模式为readw模式为writea模式为append文件读写内容的格式有两种(默认的读写内容的模式为b模式):t模式为t

    2022年7月4日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号