线程池的简单使用

一、线程池简介

        其实所有池化技术,初衷都是节约资源,提升性能,线程池也不例外,线程的创建和销毁非常耗资源,不适合在实际的工作中使用。

        线程池可以对线程进行重复利用,很好的节约了资源。

二、线程池参数介绍

int corePoolSize 核心线程数;线程池常驻线程数量
int maximumPoolSize 最大线程数;当阻塞队列已满,线程池所能扩容的最大数量
long keepAliveTime 空闲时间;扩容的线程所能存活的时间。
TimeUnit unit 空闲时间单位
BlockingQueue<Runnable> workQueue 阻塞队列;当核心线程都在工作,再有请求,就会入队列进行等待。
ThreadFactory threadFactory 线程创建工厂,一般使用默认线程创建工程即可
RejectedExecutionHandler handler 拒绝策略;当线程池中线程数量已达到最大线程数,队列也已满,再有请        
    拒绝策略类型
	AbortPolicy (默认):直接抛出 RejectedExecutionException异常阻止系统正常运知。
	CallerRunsPolicy:"调用者运行"一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。
	DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。
	DiscardPolicy:直接丢弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种方案。

三、jdk所提供的线程池

1 newSingleThreadExecutor
	> 创建方式 Executors.newSingleThreadExecutor()
	> 源码 public static ExecutorService newSingleThreadExecutor() {
        		  return new FinalizableDelegatedExecutorService
                        (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,
                                                new LinkedBlockingQueue<Runnable>()));
              }
	> 特点:线程池中只有一个工作线程,核心线程数与最大线程数一样。

2 newFixedThreadPool
	> 创建方式 Executors.newFixedThreadPool(int)
	> 源码 public static ExecutorService newFixedThreadPool(int nThreads) {
                    return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,
                                                  new LinkedBlockingQueue<Runnable>());
              }
	> 特点:自定义核心线程数与最大线程数

3 newCachedThreadPool()
	> 创建方式:Executors.newCachedThreadPool()
	> 源码 public static ExecutorService newCachedThreadPool() {
                    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,
                                                  new SynchronousQueue<Runnable>());
              }
	> 特点:不指定核心线程数与最大线程数,动态扩容。如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
	

四、不推荐Executors创建线程池

1、newSingleThreadExecutor与newFixedThreadPool未给任务队列LinkedBlockingQueue指定队列大小,而默认的队列容量极易导致内存溢出。
2、jdk自带的线程池拒绝策略默认都是AbortPolicy,直接抛异常无论是什么项目都无法接受

五、核心线程数配置说明

 1、CPU密集型
	- CPU密集的意思是该任务需要大量的运算,而没有阻塞,CPU一直全速运行。
	- CPU密集任务只有在真正的多核CPU上才可能得到加速(通过多线程)
	- CPU密集型任务配置尽可能少的线程数量
	- 公式:(CPU核数+1)个线程的线程池
 2、lO密集型
	- 由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如CPU核数 * 2
	- 在单线程上运行IO密集型的任务会导致浪费大量的CPU运算能力浪费在等待,
			所以在IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要就 
 是利用了被浪费掉的阻塞时间。
	- IO密集型时,大部分线程都阻塞,故需要多配置线程数:
			参考公式:CPU核数/ (1-阻塞系数)
			阻塞系数在0.8~0.9之间
			比如8核CPU:8/(1-0.9)=80个线程数
 3、动态获取当前机器cpu核数
		Runtime.getRuntime().availableProcessors();

六、自定义线程池

    package cn.hh.huhy;
    import java.util.Objects;
    import java.util.concurrent.*;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    /**
     * @author huhy
     */
    public class ThreadPollDemo {

        private static ThreadPollDemo threadPollDemo;

        private static Lock lock = new ReentrantLock();

        private ThreadPollDemo() {
        }

        public static final ThreadPollDemo createThreadPollDemo() {
            if (Objects.isNull(threadPollDemo)) {
                lock.lock();
                if (Objects.isNull(threadPollDemo)) {
                    threadPollDemo = new ThreadPollDemo();
                }
                lock.unlock();
            }
            return threadPollDemo;
        }

        public void doSomething(ExecutorService threadPoll, int numOfRequest) {
            System.out.println(((ThreadPoolExecutor) threadPoll).getRejectedExecutionHandler().getClass().getName() + "\n");
            try {
                for (int i = 0; i < numOfRequest; i++) {
                    final int tempInt = i;
                    threadPoll.execute(() -> {
                        System.out.println(Thread.currentThread().getName() + "\t 给用户:" + tempInt + " 办理业务");
                    });
                }
                TimeUnit.SECONDS.sleep(1L);
                System.out.println("\n\n");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                threadPoll.shutdown();
            }

        }

        public ExecutorService newHhyThreadPollExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, int queueSize, RejectedExecutionHandler handler) {
            return new ThreadPoolExecutor(corePoolSize,
                    maximumPoolSize,
                    keepAliveTime,
                    unit,
                    new LinkedBlockingQueue<>(queueSize),
                    Executors.defaultThreadFactory(),
                    handler
            );
        }

        public static void main(String[] args) {
    //        ThreadPollDemo threadPollDemo = ThreadPollDemo.createThreadPollDemo();
    //        threadPollDemo.doSomething(threadPollDemo.newHhyThreadPollExecutor(2, 5, 3, TimeUnit.SECONDS, 3, new ThreadPoolExecutor.AbortPolicy()), 10);
    //        threadPollDemo.doSomething(threadPollDemo.newHhyThreadPollExecutor(2, 5, 3, TimeUnit.SECONDS, 3, new ThreadPoolExecutor.CallerRunsPolicy()), 20);
    //        threadPollDemo.doSomething(threadPollDemo.newHhyThreadPollExecutor(2, 5, 3, TimeUnit.SECONDS, 3, new ThreadPoolExecutor.DiscardOldestPolicy()), 10);
    //        threadPollDemo.doSomething(threadPollDemo.newHhyThreadPollExecutor(2, 5, 3, TimeUnit.SECONDS, 3, new ThreadPoolExecutor.DiscardPolicy()), 10);
    //        int i = Runtime.getRuntime().availableProcessors();
    //        System.out.println("当前电脑的cpu核数为:"+i+"核");

        }
    }

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值