JAVA线程池应用

–为甚么要用线程池?

线程是不是越多越好?
1、线程在java中是一个对象,更是操作系统的资源,线程创建、销毁需要时间。
如果创建时间+销毁时间>执行任务时间 就很不合算。
2、java对象占用堆内存,操作系统线程占用系统内存,根据jvm规范,一个线程默认
最大栈大小1M,这个栈空间是需要从系统内存中分配的。线程过多,会消耗很多的内存。
3、操作系统需要频繁切换线程上下文,影响性能。

–线程池原理 - 概念
1、线程池管理器:用于创建并管理线程池,包括创建线程池,销毁线程池,添加新任务;
2、工作线程:线程池中线程,在没有任务时处于等待状态,可以循环的执行任务‘
3、任务接口:每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,
任务执行完后的收尾工作,任务的执行状态等。
4、任务队列:用于存放没有处理的任务。提供一种缓存机制。

–线程池API - 接口定义和实现类
类型 名称 描述
接口 Executor 最上层的接口,定义了执行任务的方法execute
接口 ExecutorService 继承了Executor接口,拓展了Callable、Future、关闭方法
接口 ScheduledExecutorService 继承了ExecutorService,增加了定时任务相关的方法
实现类 ThreadPoolExecutor 基础、标准的线程池实现
实现类 ScheduledThreadPoolExecutor 继承了ThreadPoolExecutor,实现了ScheduledExecutorService中相关定时任务的方法

可以认为ScheduledThreadPoolExecutor是最丰富的实现类

	ExecutorService

//监测ExecutorService是否已经关闭,直到所有任务完成执行,或超时发生,或当前线程被中断
awaitTermination(Long timeout,TimeUnit unit)
//执行给定的任务集合,执行完毕后,返回结果
invokeAll(Collection<? extends Callable<T>> tasks)
//执行给定的任务合集,执行完毕或者超时后,返回结果,其他任务终止
invokeAll(Collection<? extends Callable<T>> tasks,TimeUnit unit)
//执行给定的任务,任意一个执行成功则返回结果,其他任务终止
invokeAny(Collection<? extends Callable<T>> tasks)
//执行给定的任务,任意一个执行成功或者超时后,则返回结果,其他任务终止
invokeAny(Collection<? extends Callable<T>> tasks,long timeout,TimeUnit unit)
//如果此线程池已关闭,则返回true
isShutdown()
//如果关闭后所有任务都已完成,则返回true
isTerminated()
//优雅关闭线程池,之前提交的任务将被执行,但是不会接受新的任务
shutdown()
//尝试体制所有正在执行的任务,停止等待任务的处理,并返回等待执行任务的列表
shutdownNow()
//提交一个用于执行的Callable返回任务,并返回一个Future,用于获取Callable执行结果
submit(Callable<T> task)
//提交可运行任务以执行,并发回一个Future对象,执行结果为null
submit(Runnable task)
//提交可运行任务以执行,并返回Future,执行结果为传入的result
submit(Runnable task,T result)

–ScheduledExecutorService 定时任务
---------------创建并执行一个一次性任务过了延迟时间就会被执行
schedule(Callable callable,long delay,TimeUnit unit)
schedule(Runnable command,long delay,TimeUnit unit)
---------------创建周期性任务
过了给定的初始延迟时间,会第一次被执行,执行过程中发生了异常,那么任务就停止
一次任务执行时长超过了周期时间,下一次任务会等到该次任务执行结束,立刻执行,
这就是它和scheduleWithFixedDelay的重要区别
------scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
过了初试延迟时间,第一次被执行,后续以给定的周期时间执行,执行过程中发生了异常,那么任务就停止
一次任务执行时长超过了周期时间,下一次任务会在该次任务执行结束的时间基础上,计算执行延时。
对于超过周期的长时间处理任务的不同处理方式,这是它和scheduleAtFixedRate的重要区别
------scheduleWithFixedDelay(Runnable command,long initialDelay,long period,TimeUnit unit)

线程池API -Executors工具类
你可以自己实例化线程池,也可以用Executors创建线程池的工厂类,常用方法如下:
newFixedThreadPool(int nThreads)创建一个固定大小、任务队列容量误解的线程池。核心线程数=最大线程数。
newCachedThreadPool()创建的是一个大小无界的缓冲线程池。它的任务队列时一个同步队列。
任务加入到池中,如果池中有空闲线程,则用空闲线程执行,如无则创建新线程执行。
池中的线程空闲超过60秒,则被销毁释放。线程数随任务的多少变化。
适用于执行耗时较小的异步任务。池的核心线程数=0,最大线程数=Integer.MAX_VALUE
newSingleThreadExecutor()只有一个线程来执行无界任务队列的单一线程池。
该线程池确保任务按加入的顺序一个一个依次执行。当唯一的线程因任务异常中止时,
将创建一个新的线程来继续执行后续的任务。与newFixedThreadPool(1)的区别在于,
单一线程池的池大小在newSingThreadExecutor方法中硬编码,不能再改变的。
newScheduledThreadPool(int corePoolSize)能定时执行任务的线程池。该池的核心线程数由参数指定,
最大线程数=Integer.MAX_VALUE

package day03;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/** 线程池的使用*/
public class Demo2 {
   
	/**
	 * 测试:提交15个执行时间需要3秒的任务,看线程池的状况
	 * @throws InterruptedException  传入不同的线程池,看不同的结果
	 * 
	 */
	public void testCommon(ThreadPoolExecutor threadPoolExecutor) throws InterruptedException {
   
		//测试:提交15个执行时间需要3秒的任务,看超过大小的2个,对应的处理情况
		for(int i=0;i<15;i++) {
   
			int n=i;
			threadPoolExecutor.submit(new Runnable() {
   

				@Override
				public void run() {
   
					// TODO Auto-generated method stub
					try {
   
						System.out.println("开始执行:"+n);
						Thread.sleep(3000L);
						System.out.println("执行结束:"+n);
					} catch (InterruptedException e) {
   
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
			});
			System.out.println("任务提交成功:"+i);
		}
		//查看线程数量,查看队列等待数量
		Thread.sleep(500L);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程池在实际应用中非常常见,以下是一些常见的线程池应用实例: 1. Web服务器:在Web服务器中,可以使用线程池来处理客户端请求。每当有一个请求到达时,可以将其封装成一个任务提交给线程池线程池会自动分配线程来处理请求,从而提高服务器的并发性能。 2. 文件下载器:在文件下载器中,可以使用线程池来同时下载多个文件。每个文件可以作为一个独立的任务提交给线程池线程池会自动创建并管理多个线程来并发下载文件,加快下载速度。 3. 数据库连接池:在使用数据库连接时,可以使用线程池来管理数据库连接。通过将每个数据库操作封装成一个任务提交给线程池线程池可以管理连接的创建和释放,避免频繁地创建和关闭数据库连接,提高数据库操作的效率。 4. 定时任务调度:在定时任务调度中,可以使用线程池来执行定时任务。可以将每个定时任务封装成一个任务提交给线程池线程池会根据设定的时间间隔自动执行任务,实现定时任务的调度功能。 5. 并行计算:在需要进行大量计算的场景下,可以使用线程池来进行并行计算。将计算任务分解成多个子任务,每个子任务作为一个独立的任务提交给线程池线程池会自动创建并管理多个线程来并行执行计算任务,提高计算速度。 这些只是一些常见的应用实例,实际上线程池Java开发中的应用非常广泛,可以根据实际需求灵活地运用线程池来提高程序的性能和并发处理能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值