java实现线程池的几种方式,java中线程池的使用

  java实现线程池的几种方式,java中线程池的使用

  00-1010 Java预定义的四个线程池是什么?四个线程池有什么区别?线程池的一些重要参数是什么?如何定制线程池摘要

  00-1010 NewsingleThreadXkutor:单线程数线程池(核心线程数=最大线程数=1)newFixedThreadPool:固定线程数线程池(核心线程数=最大线程数=自定义)newCacheThreadPool:可缓存线程池(核心线程数=0,最大线程数=整数。MAX _ VALUE)newscheduledthreadpool:支持调度或周期性任务的线程池(核心线程=自定义,最大线程=integer.max _ value)

  00-1010以上四个线程池类都是继承ThreadPoolExecutor的,创建时都直接返回new ThreadPoolExecutor(参数)。两者的区别在于定义的ThreadPoolExecutor(参数)参数不同,ThreadPoolExecutor继承ExecutorService接口类。

  NewFixedThreadPool定义:executorservice executorservice=executors . NewFixedThreadPool(2);

  缺点:使用了LinkBlockQueue的链表阻塞队列。当任务的积累速度快于处理速度时,容易积累任务,导致OOM内存溢出。

  NewSingleThreadExecutor定义:Executorservice Executorservice=executors。NewSinglethreadexecutor();

  上面的代码看起来很像new FixedThreadPoop(1),但又有所不同,因为外面多了一层FinalizeableDelegateDexecutorService,它的作用是:

  可以看出,fixedExecutorService的本质是ThreadPoolExecutor,所以fixedExecutorService可以强制转换为ThreadPoolExecutor,但是singleExecutorService与ThreadPoolExecutor无关,所以强制转换失败。所以newSingleThreadExecutor()创建后,它的线程池参数就不能再修改了,它就可以真正成为一个单线程了。

  缺点:使用了LinkBlockQueue的链表阻塞队列。当任务的积累速度快于处理速度时,容易积累任务,导致OOM内存溢出。

  newCacheThreadPool

  定义:Executorservice Executorservice=executors . newcachethreadpool();

  缺点:SynchronousQueue是BlockingQueue的一个实现。它也是一个队列,因为最大线程数是整数。MAX_VALUE,所以线程太多的时候很容易溢出OOM内存。

  调度线程池

  定义:Executorservice Executorservice=executors . newscheduledthreadpool(2);

  源代码:public static scheduledexecutor服务new scheduledthreadpool(int corepoolsize){//scheduledthreadpoolexecutor继承threadpoolexecutor返回new scheduledthreadpoolexecutor(corepoolsize);} public scheduledthreadpoolexecutor(int corepoolsize){//scheduledthreadpoolexecutor继承ThreadPoolExecutor,因此,super()会调用ThreadPoolExecutor的构造函数初始化并返回一个ThreadPoolExecutor,ThreadPoolExecutor使//最终实现ExecutorService接口的scheduledThreadPoolExecutor返回ExecutorService接口的实现类threadpool executor super(corepoolsize)就像上面的线程池一样。

  , Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());}

 

  

线程池有哪几个重要参数?

ThreadPoolExecutor构造方法如下:

 

  

 

  

 

  keepAliveTime是指当前线程数位于 [核心线程数,最大线程数] 之间的这些非核心线程等待多久空闲时间而没有活干时,就退出线程池;等待丢列的大小与最大线程数是没有任何关系的,线程创建优先级=核心线程 > 阻塞队列 > 扩容的线程(当前核心线程数小于最大线程数时才能扩容线程)假如核心线程数5,等待队列长度为3,最大线程数10:当线程数不断在增加时,先创建5个核心线程,核心线程数满了再把线程丢进等待丢列,等待队列满了(3个线程),此时会比较最大线程数(只有等待丢列满了最大线程数才能出场),还可以继续创建2个线程(5+3+2),若线程数超过了最大线程数,则执行拒绝策略;假如核心线程数5,等待队列长度为3,最大线程数7:当线程数不断在增加时,先创建5个核心线程,核心线程数满了再把线程丢进等待丢列,当等待队列中有2个线程时达到了最大线程数(5+2=7),但是等待丢列还没满所以不用管最大线程数,直到等待丢列满了(3个阻塞线程),此时会比较最大线程数(只有等待丢列满了最大线程数才能出场),此时核心+等待丢列=5+3=8>7=最大线程数,即已经达到最大线程数了,则执行拒绝策略;如果把等待丢列设置为LinkedBlockingQueue无界丢列,这个丢列是无限大的,就永远不会走到判断最大线程数那一步了

 

  

如何自定义线程池

可以使用有界队列,自定义线程创建工厂ThreadFactory和拒绝策略handler来自定义线程池

 

  

public class ThreadTest { public static void main(String[] args) throws InterruptedException, IOException { int corePoolSize = 2; int maximumPoolSize = 4; long keepAliveTime = 10; TimeUnit unit = TimeUnit.SECONDS; BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2); ThreadFactory threadFactory = new NameTreadFactory(); RejectedExecutionHandler handler = new MyIgnorePolicy(); ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); executor.prestartAllCoreThreads(); // 预启动所有核心线程 for (int i = 1; i <= 10; i++) { MyTask task = new MyTask(String.valueOf(i)); executor.execute(task); } System.in.read(); //阻塞主线程 } static class NameTreadFactory implements ThreadFactory { private final AtomicInteger mThreadNum = new AtomicInteger(1); @Override public Thread newThread(Runnable r) { Thread t = new Thread(r, "my-thread-" + mThreadNum.getAndIncrement()); System.out.println(t.getName() + " has been created"); return t; } } public static class MyIgnorePolicy implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { doLog(r, e); } private void doLog(Runnable r, ThreadPoolExecutor e) { // 可做日志记录等 System.err.println( r.toString() + " rejected");// System.out.println("completedTaskCount: " + e.getCompletedTaskCount()); } } static class MyTask implements Runnable { private String name; public MyTask(String name) { this.name = name; } @Override public void run() { try { System.out.println(this.toString() + " is running!"); Thread.sleep(3000); //让任务执行慢点 } catch (InterruptedException e) { e.printStackTrace(); } } public String getName() { return name; } @Override public String toString() { return "MyTask [name=" + name + "]"; } }}

运行结果:

 

  

 

  其中7-10号线程被拒绝策略拒绝了,1、2号线程执行完后,3、6号线程进入核心线程池执行,此时4、5号线程在任务队列等待执行,3、6线程执行完再通知4、5线程执行

  

 

  

总结

到此这篇关于java自带的四种线程池的文章就介绍到这了,更多相关java四种线程池内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: