多线程和线程池的比较与理解

话不多说,直接上代码,要说的都在代码注释里面:

public class ThreadPools {
	
	//TODO:ThreadPoolExecutor的执行规则——
		//1.如果线程池中的线程数量未达到核心线程的数量,那么直接启动一个核心线程;
		//2.如果线程池中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入到任务队列中排队等待执行。
		//3.如果在步骤2中无法将任务插入到任务队列中,这往往是因为任务队列已满,这时如果线程池先吃数量未达到线程池规定的最大值,会立即启动一个非核心线程来执行任务。
		//4.如果步骤3中的线程数量已经达到线程池规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法来通知调用者。


	public static void main(String[] args) {
		ExecutorService service = getCachedThreadPool(new Runnable() {
			@Override
			public void run() {
				System.out.println("风满楼,卷黄沙,舞剑春秋,名震天下;雨缥缈,眷红尘,还君明珠,秋水浮萍,");
			}
		});
		//一定要在合适的地方调用shutdown()方法,以避免内存泄漏。
		//TODO:shutdown()关闭线程,调用这个方法的时候,线程不一定会立即关闭,因为可能任务还没有执行完毕。
		//TODO:shutdownNow()关闭线程,调用这个方法的时候,直接关闭,不管还有没有任务执行。
		//TODO:isShutdown(),只要调用了shutdown()方法,就会返回true;
		//TODO:isTerminated(),任务执行完成的后,isTerminated()方法才会返回true;
		//TODO:所以采用一个while死循环+判断isTerminated()的方法来确定任务是否执行完成。
		service.shutdown();
		System.out.println(service.isShutdown());
		System.out.println(service.isTerminated());
	}

    /**
     * 创建一个根据需要创建新线程的线程池,它没有核心线程,对线程池大小没有做限制,理论上可以有无线多个,实际上线程池大小完全依赖于JVM
     * 如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,
     * 当任务数增加时,此线程池又可以智能的添加新线程来处理任务。
     * @param runnable
     */
    public static ExecutorService getCachedThreadPool(Runnable runnable){
        ExecutorService service = Executors.newCachedThreadPool();
        service.execute(runnable);
        return service;
    }

    /**
     * 创建一个单线程的线程池
     * @param runnable
     */
    public static ExecutorService getSingleThreadPool(Runnable runnable){
        ExecutorService service = Executors.newSingleThreadExecutor();
        service.execute(runnable);
        return service;
    }

    static ExecutorService newFixedThreadPoolService = null;

    /**
     * 创建一个可重用的固定长度的线程池,控制线程最大并发数,超出的线程会在队列中等待。
     * @param nThreads:线程池长度
     * @param runnable:线程
     */
    public synchronized static ExecutorService getNewFixedThreadPool(int nThreads, Runnable runnable){
        if (null == newFixedThreadPoolService){
            newFixedThreadPoolService = Executors.newFixedThreadPool(nThreads);
        }
        newFixedThreadPoolService.submit(runnable);
        return newFixedThreadPoolService;
    }

    static ExecutorService newScheduledThreadPoolService = null;

    /**
     * 创建一个定长线程池,支持定时及周期性任务执行。
     * @param nThreads:线程池可缓存线程的数量
     * @param runnable:线程
     */
    public synchronized static ExecutorService  getScheduledThreadPool(int nThreads, Runnable runnable){
        if (newScheduledThreadPoolService == null){
            newScheduledThreadPoolService = Executors.newScheduledThreadPool(nThreads);
        }
        newScheduledThreadPoolService.submit(runnable);
        return newScheduledThreadPoolService;
    }
    
    static ScheduledExecutorService mScheduledExecutorServiceFixedRate;
    /**同getScheduledThreadPoolExecutor()方法*/
    public synchronized static ScheduledExecutorService getScheduledExecutorServiceFixedRate(
                    int nThreads, Runnable runnable, long initialDelay, long period, TimeUnit unit){
        if (mScheduledExecutorServiceFixedRate == null){
            mScheduledExecutorServiceFixedRate = Executors.newScheduledThreadPool(nThreads);
        }
        mScheduledExecutorServiceFixedRate.scheduleAtFixedRate(runnable, initialDelay, period, unit);
        return mScheduledExecutorServiceFixedRate;
    }

    static ScheduledExecutorService mScheduledExecutorServiceFixedDelay;
    /**同getScheduledThreadPoolExecutorWithFixedDelay()方法*/
    public synchronized static ScheduledExecutorService getScheduledExecutorServiceFixedDelay(
                        int nThreads, Runnable runnable, long initialDelay, long period, TimeUnit unit){
        if (mScheduledExecutorServiceFixedDelay == null){
            mScheduledExecutorServiceFixedDelay = Executors.newScheduledThreadPool(nThreads);
        }
        mScheduledExecutorServiceFixedDelay.scheduleWithFixedDelay(runnable, initialDelay, period, unit);
        return mScheduledExecutorServiceFixedDelay;
    }




//TODO:ScheduledThreadPoolExecutor创建线程池。它使用的工作队列是DelayedWorkQueue,DelayedWorkQueue是一个无界队列;我们仅仅需要指定其核心线程数量

    static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = null;
    /**
     * 创建一个可缓存并且可以周期性执行任务的线程池,优先保证任务执行的频率。
     * 该方法在initialDelay时长后第一次执行任务,以后每隔period时长,再次执行任务。
     * 如果上一个任务执行完毕,则当前任务立即执行,如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行。
     * @param nThreads:线程池可缓存线程的数量
     * @param runnable:线程
     * @param initialDelay:延迟执行的时间
     * @param period:每次任务执行的时间间隔
     * @param unit:时间单位——S,ms,min,h......
     */
    public synchronized static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor(
    				int nThreads, Runnable runnable, long initialDelay, long period,TimeUnit unit){
        if (null == scheduledThreadPoolExecutor){
            scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(nThreads);
        }
        // scheduleAtFixedRate:该方法在initialDelay时长后第一次执行任务,以后每隔period时长,再次执行任务。
        // 注意,period是从任务开始执行算起的。开始执行任务后,定时器每隔period时长检查该任务是否完成,
        // 如果完成则再次启动任务,否则等该任务结束后才再次启动任务。
        scheduledThreadPoolExecutor.scheduleAtFixedRate(runnable, initialDelay, period, unit);
        return scheduledThreadPoolExecutor;
    }

    static ScheduledThreadPoolExecutor scheduleWithFixedDelay;

    /**
     * 创建一个可缓存并且可以周期性执行任务的线程池,优先保证任务执行的间隔。
     * 任务在在initialDelay时长后第一次执行任务,以后每当任务执行完成后,等待delay时长,再次执行任务。
     * 如果任务执行过程中抛出了异常,那么过ScheduledExecutorService就会停止执行任务,且也不会再周期地执行该任务了。
     * 所以你如果想保住任务都一直被周期执行,那么catch一切可能的异常。
     * @param nThreads:线程池可缓存线程的数量
     * @param runnable:线程
     * @param initialDelay:延迟执行的时间
     * @param period:每次任务执行的时间间隔
     * @param unit:时间单位——S,ms,min,h......
     */
    public synchronized static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutorWithFixedDelay(
    						int nThreads, Runnable runnable, long initialDelay, long period, TimeUnit unit){
        if (null == scheduleWithFixedDelay){
            scheduleWithFixedDelay = new ScheduledThreadPoolExecutor(nThreads);
        }
        // 在initialDelay时长后第一次执行任务,以后每当任务执行完成后,等待delay时长,再次执行任务。
        scheduleWithFixedDelay.scheduleWithFixedDelay(runnable, initialDelay, period, unit);
        return scheduleWithFixedDelay;
    }

    static ScheduledThreadPoolExecutor scheduleService = null;
    /**
     * 创建一个可缓存并且可以周期性执行任务的线程池,任务在延迟delay时长后执行,只执行一次。
     * @param nThreads:线程池可缓存线程的数量
     * @param runnable:线程
     * @param delay:延迟执行的时间
     * @param unit:时间单位——S,ms,min,h......
     */
    public synchronized static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor(
    							int nThreads, Runnable runnable, long delay, TimeUnit unit){
        if (null == scheduleService){
            scheduleService = new ScheduledThreadPoolExecutor(nThreads);
        }
        // schedule方法调度的任务在delay时长的延迟后只执行一次。
        scheduleService.schedule(runnable, delay, unit);
        return scheduleService;
    }

    static ScheduledThreadPoolExecutor scheduleServiceExecute = null;

    /**
     * 创建一个可缓存的线程池
     * @param nThreads:线程池可缓存线程的数量
     * @param runnable:线程
     */
    public synchronized static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutorExecute(int nThreads, Runnable runnable){
        if (null == scheduleServiceExecute){
            scheduleServiceExecute = new ScheduledThreadPoolExecutor(nThreads);
        }
        // execute方法调度的任务异步执行。
        scheduleServiceExecute.execute(runnable);
        return scheduleServiceExecute;
    }
}

执行结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值