java中的线程池(基于jdk1.8)

ThreadPoolExecutor线程池执行流程流程

                线程池的作用:降低资源消耗、调高相应速度、提高线程的可管理行

本图是概况图:来源引自:https://blog.csdn.net/fuyuwei2015/article/details/72758179

         

本图是明细图                                          

RejectedExecutionHandler(拒绝策略)接口的解释:在使用线程池并使用有界队列时,如果队列满了,任务添加到线程池就会有问题,为此提供了拒绝策略。策略有以下几种:1)AbortPolicy:线程池默认的策略,如果任务添加到线程池失败,会抛出RejectedExecutionException异常;2)DiscardPolicy:如果添加任务失败,则放弃,不会抛出任何异常;3)DiscardOldesPolicy:如果任务添加到线程池失败,会将队列中最早添加的任务移除;并再次尝试添加,如果添加失败则会继续按照该策略执行;4)CallerRunsPolicy:如果任务添加失败,主线程会自己调用执行器中的execute方法来执行该任务;5)用户自定义策略:如果以上几种策略都不合适,将根据场景自定义拒绝策略,必须实现RejectedExecutionHandler接口,并将自定义的逻辑写在rejectedExecution()方法中。

                public class MyRejectPolicy implements RejectedExecutionHandler{
                        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                                                        //Sender是我的Runnable类,里面有message字段
                                                        if (r Sender) {
                                                                    Sender sender = (Sender) r;
                                                                    //直接打印
                                                                    System.out.println(sender.getMessage());
                                                        }
                                               }
                                    }

明细流程图步骤讲解:1.如果当前运行的线程少于corePoolSize(核心线程数),则创建新线程来执行任务(注意:执行这一步要获取全局锁);2.如果运营的线程等于或多余corePoolSize(核心线程数),则将任务加入到BlockingQueue(阻塞队列)。3.如果无法将任务加入BlockingQueue(阻塞队列),则在非corePool中创建新的线程处理任务(注意:执行这一步要获取全局锁)。4.如果创建新线程将使当前运行线程超出maximumPoolSize(线程池最大数量)、任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecution()方法。

备注:ThreadPoolExecutor采取上述整体设计思路,是为了在执行execute()方法时,尽可能避免获取全局锁(获取全局锁是一个严重的可伸缩瓶颈),当运行的线程数大于等于corePoolSize(核心线程数)都会执行步骤2,因为步骤2不用获取全解锁。

ThreadPoolExecutor创建线程池时的参数及方法作用

参数描述:corePoolSize:核心线程池基本大小,活动线程小于corePoolSize则直接创建,大于等于则添加到workQueue(工作队列)中,队列满了才创建新的线程,当提交一个任务到线程池时,线程池会创建一个线程来 执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不在创建、如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。maximumPoolSize:最大线程数,超过就reject(拒绝);线程池允许创建最大线程数。如果队列满了,并且已创 建的线程数小于最大线程数,则线程池会在创建新的线程执行任务。keepAliveTime:线程池的工作线程空闲后保持存活的时间,如果任务很多并且每个任务执行时间比较短,可以调大时间,提高线程利用率。unit:线程活动保持时间的单位,有天(DAYS)、小时(HOURS)、分钟(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和纳秒(NANOSECONDS,千分之一微秒)workQueue:工作队列,线程池中的工作线程都是从工作队列中获取任务进行执行的。工作队列类型包括:ArrayBlockingQueue:有界队列,FIFO,需指定队列大小,如果队列满了,会触发线程池的RejectedExecutionHandler逻辑LinkedBlockingQueue:无界队列,FIFO,可以无限向队列添加任务,直到内存溢出SynchronousQueue:阻塞队列,每个put必须等待一个take,同步队列的容量只有1个队列,其中Executors.newCachedThreadPool使用的就是该队列PriorityBlockingQueue:优先级队列,线程池会优先选取级别高的任务执行,队列中的元素必须实现Comparable接口threadFactory:新建工厂,使用new CustomThreadFactory定制线程工厂RejectedExecutionHandler(拒绝策略):当提交任务数超过maximumPoolSize(线程最大数)+workQueue(工作 队列)之和时,任务会交给 RejectedExecutionHandler(拒绝策略)来处理;

方法描述:

execute():向线程池提交任务,该方法没有返回值,不会返回执行结果,该方法需要传入Runnable类的实例。 

        threadsPool.execute(new Runnable() {
                @Override
                public void run() {}

        });    

submit():向线程池提交任务,会返回future对象,通过future对象判断任务是否执行成功,并通过uture对象的get()方法获取返回值。其中get()方法会阻塞当前线程直到任务完成,而get(long timeout,TimeUnit  unit)方法则会阻塞当前线程一段时间后立即返回, 这时有可能任务没有执行完。

 Future<Object> future = executor.submit(harReturnValuetask);
                             try{
                                 Object s = future.get();
                             }catch(InterruptedException e){
                                  // 处理中断异常
                             }catch(ExecutionException e){
                                  // 处理无法执行任务异常
                             }finally{
                                 // 关闭线程池
                                 executor.shutdown();
 }

shutdown():关闭线程池,将线程池变成shutdownNow状态,此时不能再往线程池中添加新任务,否则会抛出RejectedExecutionException异常,此时线程池不会立刻退出,直到添加到线程池中的任务都已处理完成,才会退出。

shutdownNow:关闭线程池并中断任务,将线程池立刻变成stop状态,此时不能再往线程池添加新任务, 终止等待执行的线程,并返回它们的列表。该方法并不能保证线程池就一定会立即退出。

ThreadPoolExecutor类的结构

       ThreadPoolExecutor继承AbstractExecutorService(抽象类),其中AbstractExecutorService(抽象类)实现ExecutorService接口,其中ExecutorService接口继承Executor接口

      1.Executor接口中的方法有

             public interface Executor {
                    void execute(Runnable command);//向线程池提交任务
             }

     2.ExecutorService接口中的方法有

                public interface ExecutorService extends Executor {
			//关闭Executor,不再接受提交任务
			void shutdown();
			//关闭Executor,不再接受提交任务,并且不再执行入队列中的任务
			List<Runnable> shutdownNow();
			//通过ctl属性判断当前的状态是否不是RUNNING状态
			boolean isShutdown();
			//通过ctl属性判断当前的状态是否为TERMINATED状态
			boolean isTerminated();
			//阻塞等待shutdown请求后所有线程终止,会有时间参数,超时和中断也会令方法调用结束
			boolean awaitTermination(long timeout, TimeUnit unit)
				throws InterruptedException;
		   
			<T> Future<T> submit(Callable<T> task);
			<T> Future<T> submit(Runnable task, T result);
			Future<?> submit(Runnable task);
			<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
				throws InterruptedException;
			<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
										  long timeout, TimeUnit unit)
				throws InterruptedException;
			<T> T invokeAny(Collection<? extends Callable<T>> tasks)
				throws InterruptedException, ExecutionException;
			<T> T invokeAny(Collection<? extends Callable<T>> tasks,
							long timeout, TimeUnit unit)
				throws InterruptedException, ExecutionException, TimeoutException;
                    }

        3.AbstractExecutorService(抽象类)是ExecutorSer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值