通过标准库创建线程池

线程池提高利用线程效率的原因

        线程池可以提高我们利用线程的效率,比通过系统频繁的进行线程的创建和销毁要快很多

        我们可以在线程池中先创建好多个线程,当要进行使用的时候从线程池中取出来使用,使用完毕放回线程池中以待下次使用

        为什么我们从池子中取线程,就比从系统这里创建线程更快更高效呢?

        如果是从系统这里创建线程,就需要调用系统api,进一步的由操作系统内核,完成线程的创建,但内核是给所有的进程提供服务的,所以内核什么时候帮你创建线程是不可控的

        如果是从线程池这里获取线程,上述在内核中进行的操作,都是提前做好了的,现在取线程的过程,是完全由用户进行控制的,用户想要什么时候获取到线程,就什么时候能够获取到,是可控的

通过工厂类创建线程

        工厂模式概念可以看:工厂模式概念

        1.实例化线程池的案例代码

ExecutorService service1= Executors.newFixedThreadPool(4);   //创造一个固定线程数量的线程池
ExecutorService service2=Executors.newCachedThreadPool();   //创建一个线程动态变化的线程池
ExecutorService service3=Executors.newSingleThreadExecutor();   //创建单个线程(比原生的创建线程api更简单一点)
//类似于定时器的效果,添加一些任务,任务都在后续的莫个时刻再执行
//被执行的时候不是只有一个扫描线程来执行任务,可能是由多个线程共同执行所有的任务
ExecutorService service4=Executors.newScheduledThreadPool(4);

        2.向线程池中添加任务的案例代码

//循环1000次,通过submit向线程池中添加1000个任务,线程池中的线程会解决添加到线程中的任务
        for(int i=0;i<1000;i++){
            service1.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello");
                }
            });
        }

        该代码的意思是循环1000次,通过submit向线程池中添加1000个打印“hello”的任务,线程池中的线程会解决添加到线程中的任务。

        线程池对象通过调用submit方法来向线程池中添加任务,submit的参数是Runnable类型的对象,通过重写Runnable类型的对象中的run方法来规定添加的任务内容。

通过ThreadPoolExecutor类来创建线程池

        1.ThreadPoolExecutor类的介绍

        ThreadPoolExecutor是最全面的创建线程池的类,Executors工厂类创建线程池是对ThreadPoolExecutor进行进一步封装的(ThreadPoolExecutor创建线程池是原生的,Executors是封装过的)

        ThreadPoolExecutor里面的线程个数,并非是固定不变的,会根据当前任务的情况动态发生变化(自适应)

         2.ThreadPoolExecutor类的参数介绍

        

ThreadPoolExecutor executor=new ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadfactory,RejectedExecutionHandle handler)

        1.corePoolSize核心线程数,至少得有这些线程,哪怕你的线程池一点任务都没有

        2.maximumPoolSize最大线程数,最多不能超过这些线程,哪怕你的线程池以及忙冒烟了也不能比这个数目更多

        3.keepAliveTime允许线程可以空闲的最大时间数值,TimeUnit是这个时间数值的单位(比如keepAliveTime为3000,TimeUnit为ms,表示3000ms后还没有任务的非核心线程(扩充的线程)就要被销毁,保证了线程池的自适应)

        4.workQueue表示一个管理线程池任务的阻塞队列,任务添加到阻塞队列workQueue中,线程去阻塞队列中获取任务进行执行

        5.threadfactory表示线程工厂,涉及到工厂模式,通过这个工厂类来创建线程

        6.handler表示拒绝方式/拒绝策略,线程池中有一个阻塞队列,当阻塞队列满了以后,继续添加任务,该如何处理?

目前标准库已经提供了四种策略(这四种处理策略是很重要的

(1).ThreadPoolExecutor.AbortPolicy 当线程池中的阻塞队列满了以后再添加任务就直接抛出异常,线程池就不干活了(相当于新添加的任务不会干,以及阻塞队列中还没有执行的任务也不会干了)

(2).ThreadPoolExecutor.CallerRunsPolicy 谁是添加这个任务的线程,谁就去执行这个任务

(3).ThreadPoolExecutor.DiscardOldestPolicy 丢弃最早的任务,添加新的任务

(4).ThreadPoolExecutor.DiscardPolicy 丢弃掉新的任务

        

你可能感兴趣的:(java,jvm,开发语言)