精华内容
下载资源
问答
  • Java线程池核心线程数最大线程数的区别
    万次阅读 多人点赞
    2020-06-23 15:20:45

    线程池策略

    corePoolSize:核心线程数;maximunPoolSize:最大线程数
    每当有新的任务到线程池时,
    第一步: 先判断线程池中当前线程数量是否达到了corePoolSize,若未达到,则新建线程运行此任务,且任务结束后将该线程保留在线程池中,不做销毁处理,若当前线程数量已达到corePoolSize,则进入下一步;
    第二步: 判断工作队列(workQueue)是否已满,未满则将新的任务提交到工作队列中,满了则进入下一步;
    第三步: 判断线程池中的线程数量是否达到了maxumunPoolSize,如果未达到,则新建一个工作线程来执行这个任务,如果达到了则使用饱和策略来处理这个任务。注意: 在线程池中的线程数量超过corePoolSize时,每当有线程的空闲时间超过了keepAliveTime,这个线程就会被终止。直到线程池中线程的数量不大于corePoolSize为止。
    (由第三步可知,在一般情况下,Java线程池中会长期保持corePoolSize个线程。)

    饱和策略

    当工作队列满且线程个数达到maximunPoolSize后所采取的策略
    AbortPolicy:默认策略;新任务提交时直接抛出未检查的异常RejectedExecutionException,该异常可由调用者捕获。
    CallerRunsPolicy:既不抛弃任务也不抛出异常,使用调用者所在线程运行新的任务。
    DiscardPolicy:丢弃新的任务,且不抛出异常。
    DiscardOldestPolicy:调用poll方法丢弃工作队列队头的任务,然后尝试提交新任务
    自定义策略:根据用户需要定制。

    更多相关内容
  • 主要介绍了JAVA 自定义线程池最大线程数设置方法,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
  • maximunPoolSize:最大线程数 每当有新的任务到线程池时,第一步: 先判断线程池中当前线程数量是否达到了corePoolSize,若未达到,则新建线程运行此任务,且任务结束后将该线程保留在线程池中,不做销毁处理,若...

    线程池策略

    corePoolSize:核心线程数;maximunPoolSize:最大线程数

    每当有新的任务到线程池时,
    第一步: 先判断线程池中当前线程数量是否达到了corePoolSize,若未达到,则新建线程运行此任务,且任务结束后将该线程保留在线程池中,不做销毁处理(如果来了新的任务有空闲的核心线程,则不创建新的线程,使用空闲核心线程执行任务),若当前线程数量已达到corePoolSize,则进入下一步;
    第二步: 判断工作队列(workQueue)是否已满,未满则将新的任务提交到工作队列中,满了则进入下一步;
    第三步: 判断线程池中的线程数量是否达到了maxumunPoolSize,如果未达到,则新建一个工作线程来执行这个任务,如果达到了则使用饱和策略来处理这个任务。注意: 在线程池中的线程数量超过corePoolSize时,每当有线程的空闲时间超过了keepAliveTime,这个线程就会被终止。直到线程池中线程的数量不大于corePoolSize为止。
    (由第三步可知,在一般情况下,Java线程池中会长期保持corePoolSize个线程。)

    饱和策略

    当工作队列满且线程个数达到maximunPoolSize后所采取的策略
    AbortPolicy:默认策略;新任务提交时直接抛出未检查的异常RejectedExecutionException,该异常可由调用者捕获。
    CallerRunsPolicy:既不抛弃任务也不抛出异常,使用调用者所在线程运行新的任务。
    DiscardPolicy:丢弃新的任务,且不抛出异常。
    DiscardOldestPolicy:调用poll方法丢弃工作队列队头的任务,然后尝试提交新任务
    自定义策略:根据用户需要定制。

    到此Java 线程池核心线程数与最大线程数的区别介绍完成。

    展开全文
  • 线程池 最大线程数

    千次阅读 2021-03-07 04:28:39
    java.lang.OutOfMemoryError: unable to create new native threadat java.lang.Thread.start0(Native Method) ~[na:1.7.0_45]at java.lang.Thread.start(Thread.java:713) ~[na:1.7.0_45]at java.util.concurrent.T...

    java.lang.OutOfMemoryError: unable to create new native thread

    at java.lang.Thread.start0(Native Method) ~[na:1.7.0_45]

    at java.lang.Thread.start(Thread.java:713) ~[na:1.7.0_45]

    at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:949) ~[na:1.7.0_45]

    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1360) ~[na:1.7.0_45]

    at org.apache.thrift.server.TThreadedSelectorServer.requestInvoke(TThreadedSelectorServer.java:306) ~[libthrift-0.9.3.jar:0.9.3]

    at org.apache.thrift.server.AbstractNonblockingServer$AbstractSelectThread.handleRead(AbstractNonblockingServer.java:210) ~[libthrift-0.9.3.jar:0.9.3]

    at org.apache.thrift.server.TThreadedSelectorServer$SelectorThread.select(TThreadedSelectorServer.java:586) ~[libthrift-0.9.3.jar:0.9.3]

    at org.apache.thrift.server.TThreadedSelectorServer$SelectorThread.run(TThreadedSelectorServer.java:541) ~[libthrift-0.9.3.jar:0.9.3]

    直观的看这个异常,会让人想到是堆内存不够用, 调节-Xmx1024m 参数以后,问题依旧。

    接着用jconsole attach到flume agent这个进程,查看堆内存的使用量, 远没有达到预设的xmx阈值。

    但是·有一个表现就是线程数猛涨到2000以后,直接掉到了20左右,为什么会创建这么多线程呢, 都是什么线程呢?

    结合thrift source 的源码, 发现thrift server 采用的也是java nio   , 有SelectorThread做socket的read/write 就绪select

    AcceptorThread做socket的accept的select ,而socket读就绪以后,收到的FrameBuffer会被包装成一个Runnable丢到线程池处理(查看

    TThreadedSelectorServer的304 行),代码如下:

    protected boolean requestInvoke(FrameBuffer frameBuffer) {

    Runnable invocation = getRunnable(frameBuffer);

    if (invoker != null) {

    try {

    invoker.execute(invocation);

    return true;

    } catch (RejectedExecutionException rx) {

    LOGGER.warn("ExecutorService rejected execution!", rx);

    return false;

    }

    } else {

    // Invoke on the caller's thread

    invocation.run();

    return true;

    }

    }

    这个任务invocation的处理逻辑是在ThriftSource的ThriftSourceHandler定义的,也就是把thrift flume event直接丢到memchannel以后返回。起初 ,我怀疑是不是flume event丢到memchannel处理太慢(比如有线程死锁),导致线程堆积, 但后面换成file channel

    问题依旧,于是继续看jconsole上thrift 的Flume 线程,因为线程工厂在创建线程的时候,指定了线程名:

    ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(

    "Flume Thrift IPC Thread %d").build();

    if (maxThreads == 0) {

    sourceService = Executors.newCachedThreadPool(threadFactory);

    } else {

    sourceService = Executors.newFixedThreadPool(maxThreads, threadFactory);

    }

    所以, 查看这些线程发现这些线程:

    堆栈跟踪:

    sun.misc.Unsafe.park(Native Method)

    java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)

    java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)

    java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)

    java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)

    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)

    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

    java.lang.Thread.run(Thread.java:744)

    说明线程池中的这些线程都在等任务工作, 既然大量的线程都在等任务,为什么还要创建这么多线程呢?是不是因为超过了单进程最大可建立的线程数呢,

    结合ThriftSource源码,发现不指定最大线程数时, thrift server的线程池的确是不停的新建线程,而maxThreads又是一个Integer.MAX_VALUE,

    if (maxThreads == 0) {

    sourceService = Executors.newCachedThreadPool(threadFactory);

    } else {

    sourceService = Executors.newFixedThreadPool(maxThreads, threadFactory);

    }

    试着在flume 配置文件中指定最大线程数:

    a1.channels.r1.threads=10

    问题解决。

    这个问题的解决也让我们反思线程池的使用,不要设定太大的最大线程数。

    展开全文
  • Java线程池的核心线程数最大线程数

    千次阅读 多人点赞 2021-03-14 19:24:35
    下面我们先来了解一下Java线程池的参数。 希望看完这篇文章后, 再提起线程池的时候, 你脑海首先出现的, 会是一个花瓶 : ) 1线程池的参数意义 Java线程池的构造函数如下: public ThreadPoolExecutor( int ...

    Java的线程池就像是一个花瓶容器。

    而把任务提交给线程池就像是把小球塞进花瓶。

    整个过程就像下面这个有趣的动画:

    下面我们先来了解一下Java线程池的参数。

    希望看完这篇文章后, 再提起线程池的时候, 你脑海首先出现的, 会是一个花瓶 : )


    线程池的参数意义

    Java线程池的构造函数如下:

    public ThreadPoolExecutor(
      int corePoolSize,
      int maximumPoolSize,
      long keepAliveTime,
      TimeUnit unit,
      BlockingQueue<Runnable> workQueue,
      ThreadFactory threadFactory,
      RejectedExecutionHandler handler) {
        //...
    }

    线程池有这么几个重要的参数:

    • corePoolSize=> 线程池里的核心线程数量
    • maximumPoolSize=> 线程池里允许有的最大线程数量
    • keepAliveTime=> 空闲线程存活时间
    • unit=> keepAliveTime的时间单位,比如分钟,小时等
    • workQueue=> 缓冲队列
    • threadFactory=> 线程工厂用来创建新的线程放入线程池
    • handler=> 线程池拒绝任务的处理策略,比如抛出异常等策略

    线程池大体的原理就是这样的:corePoolSize ->queue -> maxPoolSzie , 吧啦吧啦......

    那么现在重点来了, 这堆参数解释不看源码真的搞不懂怎么办?

    或者你看懂了这些参数的文字解析,但是到用的时候总是记不住怎么办?

    或者我们来一组实际参数,你能理解这代表的含义吗?

    corePoolSize:1
    mamximumPoolSize:3
    keepAliveTime:60s
    workQueue:ArrayBlockingQueue,有界阻塞队列,队列大小是4
    handler:默认的策略,抛出来一个ThreadPoolRejectException

    别慌,我们可以把线程池的参数做成花瓶的参数,这样一来很多东西就不言自明了。

    线程池的参数可视化

    我们回到前面所说的花瓶。

    这个花瓶由 瓶口 、 瓶颈 、 瓶身 三个部分组成。

    这三个部分分别对应着线程池的三个参数:maximumPoolSize, workQueue,corePoolSize。

    线程池里的线程,我用一个红色小球表示,每来一个任务,就会生成一个小球:

    而核心线程,也就是正在处理中的任务,则用灰色的虚线小球表示 (目前第一版动画先这样简陋点吧......)

    于是画风就变成了这样,“花瓶”有这么几个重要的参数:

    • corePoolSize=> 瓶身的容量
    • maximumPoolSize=> 瓶口的容量
    • keepAliveTime=> 红色小球的存活时间
    • unit=> keepAliveTime的时间单位,比如分钟,小时等
    • workQueue=> 瓶颈,不同类型的瓶颈容量不同
    • threadFactory=> 你投递小球进花瓶的小手 (线程工厂)
    • handler=> 线程池拒绝任务的处理策略,比如小球被排出瓶外

    如果往这个花瓶里面放入很多小球时(线程池执行任务);

    瓶身 (corePoolSize) 装不下了, 就会堆积到 瓶颈 (queue) 的位置;

    瓶颈还是装不下, 就会堆积到 瓶口 (maximumPoolSize);

    直到最后小球从瓶口溢出。

    还记得上面提到的那一组实际参数吗,代表的花瓶大体上是如下图这样的:

    那么参数可视化到底有什么实际意义呢?


    3 阿里的规范

    首先我们来看阿里开发手册中对于 Java 线程池的使用规范:

    为什么规范中提及的四种线程会导致OOM呢?

    我们看看这四种线程池的具体参数,然后再用花瓶动画演示一下导致OOM的原因。

    线程池FixedThreadPool

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
        0L, TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<Runnable>());

    我们关心的参数如下

    corePoolSize:nThreads
    mamximumPoolSize:nThreads
    workQueue:LinkedBlockingQueue

    FixedThreadPool表示的花瓶就是下图这样子:

    线程池SingleThreadPool:

    public static ExecutorService newSingleThreadExecutor() {
          return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
             0L, TimeUnit.MILLISECONDS,
             new LinkedBlockingQueue<Runnable>()));
    ​  }

    我们关心的参数如下

    corePoolSize:1
    mamximumPoolSize:1
    workQueue:LinkedBlockingQueue

    SingleThreadPool表示的花瓶就是下图这样子:


    虽然两个线程池的样子没什么差异,但是这里我们发现了一个问题:

    为什么 FixedThreadPool 和 SingleThreadPool 的 corePoolSize和mamximumPoolSize 要设计成一样的?

    回答这个问题, 我们应该关注一下线程池的 workQueue 参数。

    线程池FixedThreadPool和SingleThreadPool 都用到的阻塞队列 LinkedBlockingQueue。

    LinkedBlockingQueue

    The capacity, if unspecified, is equal to {@link Integer#MAX_VALUE}. Linked nodes are dynamically created upon each insertion unless this would bring the queue above capacity.

    从LinkedBlockingQueue的源码注释中我们可以看到, 如果不指定队列的容量, 那么默认就是接近无限大的。

    从动画可以看出, 花瓶的瓶颈是会无限变长的, 也就是说不管瓶口容量设计得多大, 都是没有作用的!

    所以不管线程池FixedThreadPool和SingleThreadPool 的mamximumPoolSize 等于多少, 都是不生效的!


    线程池CachedThreadPool

    public static ExecutorService newCachedThreadPool() {
      return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
      60L, TimeUnit.SECONDS,
      new SynchronousQueue<Runnable>());

    我们关心的参数如下

    corePoolSize:0
    mamximumPoolSize:Integer.MAX_VALUE
    workQueue:SynchronousQueue

    表示的花瓶就是下图这样子:

    这里我们由发现了一个问题:

    为什么CachedThreadPool的mamximumPoolSize要设计成接近无限大的?

    回答这个问题, 我们再看一下线程池CachedThreadPool的 workQueue 参数:SynchronousQueue。

    SynchronousQueue

    来看SynchronousQueue的源码注释:

    A synchronous queue does not have any internal capacity, not even a capacity of one.

    从注释中我们可以看到, 同步队列可以认为是容量为0。

    所以如果mamximumPoolSize不设计得很大, 就很容易导致溢出。

    但是瓶口设置得太大,堆积的小球太多,又会导致OOM(内存溢出)。

    线程池ScheduledThreadPool

    public ScheduledThreadPoolExecutor(int corePoolSize) {
      super(corePoolSize, Integer.MAX_VALUE, 
      0, NANOSECONDS,
      new DelayedWorkQueue());
    }

    我们关心的参数如下

    corePoolSize:corePoolSize
    mamximumPoolSize:Integer.MAX_VALUE
    workQueue:DelayedWorkQueue

    可以看到, 这里出现了一个新的队列 workQueue:DelayedWorkQueue

    DelayedWorkQueue

    DelayedWorkQueue 是无界队列, 基于数组实现, 队列的长度可以扩容到 Integer.MAX_VALUE。

    同时ScheduledThreadPool的 mamximumPoolSize 也是接近无限大的。

    可以想象得到,ScheduledThreadPool就是史上最强花瓶, 极端情况下长度已经突破天际了!

    到这里, 相信大家已经明白, 为什么这四种线程会导致OOM了。

    怎么感觉这四种线程还真是名副其实的“花瓶”呢 :)


    后续

    目前花瓶动画还只是粗略的版本, 有部分瑕疵是不可避免的, 根据二八定律, 我的主要想法大体上是先做出来了,剩下的细节再慢慢补。

    目前只体现了线程池的三个参数。

    如果现在加入参数 keepAliveTime, 那么动画又会有什么效果的呢?

    敬请期待后续更新的文章。


    可视化的意义

    有很多人或许会认为, 学习个线程池, 还要做什么动画, 这不是走偏了吗?

    引用大神的一句话回答这个问题:

    Data visualization knowledge is not necessary -- just the desire to spread some knowledge.

    —— Ben Johnson

    数据可视化确实不是必需的, 但是有时候我们仅仅只是渴望给大家分享一些知识。

    而且在这个分享的过程中, 动画会让你做出更多的思考:

    思考动画怎么才能符合真实场景的效果。

    比如当我们开始思考,动画中花瓶颈部的长度变化,以及DelayedWorkQueue队列容量的变化,这两者如何才能对应的上时,于是不可避免的, 我们会开始研究起DelayedWorkQueue的扩容方式

    甚至每一种队列都可以单独展开做成更加细化的动画。

    而想要做好这些动画, 又要开始研究不同队列的源码了, 有需求才有动力!

    /**
     * 简单配置示例
     */
    
    //获取当前机器的核数
    public static final int cpuNum = Runtime.getRuntime().availableProcessors();
    
    @Override
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
            taskExecutor.setCorePoolSize(cpuNum);//核心线程大小
            taskExecutor.setMaxPoolSize(cpuNum * 2);//最大线程大小
            taskExecutor.setQueueCapacity(500);//队列最大容量
            //当提交的任务个数大于QueueCapacity,就需要设置该参数,但spring提供的都不太满足业务场景,可以自定义一个,也可以注意不要超过QueueCapacity即可
            taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
            taskExecutor.setAwaitTerminationSeconds(60);
            taskExecutor.setThreadNamePrefix("BCarLogo-Thread-");
            taskExecutor.initialize();
            return taskExecutor;
        }
    
    

     

    展开全文
  • 下面小编就为大家带来一篇java线程池:获取运行线程数并控制线程启动速度的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 在高并发的情况下采用线程池,可以有效降低线程创建释放的时间花销及资源开销,如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及“过度切换”(在JVM中采用的处理机制为时间片轮转,减少了线程间...
  • 摘自: Java线程池的核心线程数最大线程数总是容易混淆怎么办
  • 线程池应该设置多大,取决于你处理的任务类型。对于CPU密集型的任务,因为线程中基本不会有阻塞导致让出CPU,只有在时间片用完以后,才可能让出CPU,这种情况发生线程切换的次数要少很多,因此不建议设置太大,netty...
  • java线程池常用参数设置

    千次阅读 2021-02-12 11:20:07
    Java编码的过程中,我们经常会创建一个线程来提高程序的执行效率,虽然这样实现起来很方便,但是会有一个问题:如果并发的线程数多,并且每个线程都是执行一个时间很短的任务就结束了,这样会造成频繁的创建和销毁...
  • 主要介绍了Java判断线程池线程是否执行完毕,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 1、当提交一个新任务到线程池时首先线程池判断基本线程池(corePoolSize)是否已满?没满,创建一个工作线程来执行任务。满了,则进入下个流程;其次线程池判断工作队列(workQueue)是否已满?没满,则将新提交的任务...
  • java线程池合理设置最大线程数和核心线程数

    万次阅读 多人点赞 2020-10-10 17:13:31
    这个时候就需要使用多线程去处理。 一开始是这么配置的: @Configuration @EnableAsync(proxyTargetClass = true)//利用@EnableAsync注解开启异步任务支持 @ComponentScan({"com.ctfojt.auditbcarslogo.service"}) /...
  • Java 确定线程池中工作线程数的大小

    万次阅读 2018-09-12 16:20:17
    a、服务器cpu核数有限,所以同时并发或者并行的线程数是有限的,所以1核cpu设置1000个线程是没有意义的。  b、线程切换也是有开销的。频繁切换线程会使性能降低。 2、调用sleep()函数的时候,县城是否会占用着CPU...
  • 瓶口:最大线程数 瓶颈:队列 瓶身容量:核心线程数 线程池SingleThreadPool 和线程池FixedThreadPool wesi
  • 为什么要用线程池? 减少了创建和销毁线程的次数,每个工作线程...corePoolSize 线程池核心线程数 maximumPoolSize 线程池最大线程数量 keepAliveTime 空闲线程存活时间 unit 空闲线程存活时间单位 workQueue 工.
  • java线程池线程优先级 Java线程优先级 (Java Thread Priorities) Priority of a thread describes how early it gets execution and selected by the thread scheduler. In Java, when we create a thread, ...
  • 1、当提交一个新任务到线程池时首先线程池判断基本线程池(corePoolSize)是否已满?没满,创建一个工作线程来执行任务。...如果线程池中的线程数量大于 corePoolSize 时,如果某线程空闲时间超过keepAliveTim
  • //想、向线程池中放入三个任务 exes.execute(new Task()); exes.execute(new Task()); exes.execute(new Task()); Thread.sleep(500);//延迟500ms,因为三个任务放入需要时间 //将exes转换为ThreadPoolExecutor,...
  • Java线程池设置线程名称

    千次阅读 2020-06-15 14:00:19
    Java线程池中三种方式创建 ThreadFactory 设置线程名称
  • ThreadPoolExecutor是JDK中的线程池实现,这个类实现了一个线程池需要的各个方法,它实现了任务提交、线程管理、监控等等方法。 来看看ThreadPoolExecutor类的构造方法源码,其他创建线程池的方法最终都会导向这个...
  • java里, 我们可以使用Executors.newFixedThreadPool 来创建线程池, 然后就可以不停的创建新任务,并用线程池来执行了。在提交任务时,如果线程池已经被占满,任务会进到一个队列里等待执行。这种机制在一些特定...
  • 下面小编就为大家带来一篇java 可重启线程线程池类的设计(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • java线程池停止线程 停止线程 (Stopping a thread) As we know that there are no direct or shortcut ways to stop thread in Java. 众所周知,在Java中没有直接或快捷的方式来停止线程。 As we know thread in ...
  • 提到,线程池的数量,也许我们能想到通过java相关的api,比如ThreadPollExecutor的构造去设置。但是线程池线程数量上线是多少呢,有如何合理估算线程数量保证性能呢,如果脑子里是问号,请往下看。 总得来说,...
  • java线程池如何合理配置核心线程数

    万次阅读 热门讨论 2019-07-09 22:21:36
    线程池合理的线程数你是如何考虑的?这也是之前面试遇到的一个题: 1.先看下机器的CPU核数,然后在设定具体参数: System.out.println(Runtime.getRuntime().availableProcessors()); 即CPU核数 =Runtime....
  • NULL 博文链接:https://waitingkkk-163-com.iteye.com/blog/2232286
  • 很多人可能有和我一样的认知:线程池启动会先创建核心线程,然后存储阻塞队列,再创建线程直到当前池里的线程数最大线程数走拒绝策略。既然核心线程数设置0那么不会创建线程。 线上运行的代码肯定没问题,那一定是...
  • 线程池最大线程数设置为多少

    千次阅读 2020-12-22 17:58:59
    线程池最大线程数设置为多少 https://blog.csdn.net/xiewenfeng520/article/details/106996050/

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 276,471
精华内容 110,588
关键字:

java线程池最大线程数

java 订阅