精华内容
下载资源
问答
  • 主要介绍了Spring Cloud Hystrix 线程池队列配置(踩坑),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 递归线程池队列

    2018-04-12 10:13:40
    注意标题里面有三个keyword,递归 线程池 队列这是我在开发爬虫程序时候碰到的需求,我们知道爬网页一般都使用广度优先搜索,每个页面下面都可能有下层页面。为了加快爬行速度,我们很容易想到用多线程来实现。但是多...

    注意标题里面有三个keyword,递归 线程池 队列

    这是我在开发爬虫程序时候碰到的需求,我们知道爬网页一般都使用广度优先搜索,每个页面下面都可能有下层页面。为了加快爬行速度,我们很容易想到用多线程来实现。

    但是多线程必须受控,不能无限的创建线程,这样机器受不了,服务器也受不了。所以多线程必须满足下面条件:

    线程数限制,超过限制则加入到队列中等待。同时,线程中允许创建新的线程,我称之为递归线程。

    根据这个需求,所以有了标题:递归线程池队列

    下面是实现代码

    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace MediaSpider {
        class TaskQueue {
            int poolSize;
            Task[] pool;
            ConcurrentQueue<Action> queue;
            CancellationTokenSource cancelTokenSource=null;
    
            public TaskQueue(int poolSize) {
                this.poolSize = poolSize;
                // 初始化线程池
                pool = new Task[poolSize];
                for (int i = 0; i < poolSize; i++) {
                    pool[i] = Task.Run(() => { });
                }
                queue = new ConcurrentQueue<Action>();
            }
            public void Add(Action action) {
                queue.Enqueue(action);
                if(cancelTokenSource!=null) cancelTokenSource.Cancel();
            }
            public void Wait() {
                while (true)
                {
                    cancelTokenSource = null;
                    int index = Task.WaitAny(pool);
    
                    // 如果队列不为空,则加入线程池执行
                    if (queue.TryDequeue(out Action action))
                    {
                        pool[index] = Task.Run(action);
                        continue;
                    }
                    cancelTokenSource = new CancellationTokenSource();
    
                    try
                    {
                        // 等待线程池所有线程都执行完毕
                        Task.WaitAll(pool, cancelTokenSource.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        // 如果队列追加,则执行队列的任务
                        continue;
                    }
                    // 如果都执行完毕,则退出等待
                    return;
                }
            }
    
        }
    
    }

    调用方法

                    pool = new TaskQueue(6);//初始化线程池,大小为6
                    pool.Add(() => { Task.Delay(100); });//添加任务
                    pool.Add(() => { Task.Delay(100); });//添加任务
                    pool.Add(() => { Task.Delay(100); });//添加任务
                    pool.Wait();//等待任务执行完毕

    实现的思路如下:

    主线程只是守护线程,任务都在其他线程里面实现。

    守护线程(Wait)实现下面的功能

    1.线程调度:当线程池有空闲的时候,把队列中的线程加入线程池执行

    2.等待全部线程池和队列执行完毕


    实现中遇到的问题

    必须等待线程池和队列同时为空才能算执行完毕,线程也会不停的创建新的线程。

    如果没有递归就比较好办,有了递归,队列都执行完了,线程池中的线程还可以添加队列。不能够单纯的WaitAll。想了几个方式,都有些问题。后来发现WaitAll(Task[], CancellationToken)是可以被打断的,才最终解决这个问题。

    如果不需要递归,那么用普通的WaitAll就可以了,代码还可以简化。

    任务队列刚开始是用Queue来实现的,由于不是线程安全需要Lock来互斥,后来发现线程安全的ConcurrentQueue,就把Lock去掉,提高了性能



    展开全文
  • 合理的设置线程池队列长度

    万次阅读 2017-11-18 13:04:49
    在实际工作中,经常会用到线程池,那么如何设置线程池队列长度,如果长度设置的不合理就无法发挥出多线程的威力。那么队列长度究竟应该设置多大呢?其实要取决于使用场景?比如你是全程异步的系统你的队列设置为0,...

    0 概述

    在实际工作中,经常会用到线程池,那么如何设置线程池队列长度,如果长度设置的不合理就无法发挥出多线程的威力。那么队列长度究竟应该设置多大呢?其实要取决于使用场景;比如你是全程异步的系统你的队列设置为0,corePoolSize设置为cpu核数。本文主要通过研究tomcat、Dubbo等业界成熟的产品是如何设置线程队列的,然后分析究竟如何合理的设置线程池队列长度。

    1 JDK线程池策略

    先增加线程至corePoolSize,之后放入队列,如队列满则增加线程至maximumPoolSize。具体可以参考:JDK线程池源码分析
    其实我们不难发现如何队列长度设置无限长度,那么线程池个数将只会增加到corePoolSize
    ,如果corePoolSize个数设置又过小,这样就会无法发挥出多线程的威力。

    2 Tomcat线程池策略

    Tomcat的线程池队列是无限长度的,但是线程池会一直创建到maximumPoolSize,然后才把请求放入等待队列中

    tomcat 任务队列org.apache.tomcat.util.threads.TaskQueue其继承与LinkedBlockingQueue,覆写offer方法。

        @Override
        public boolean offer(Runnable o) {
          //we can't do any checks
            if (parent==null) return super.offer(o);
            //we are maxed out on threads, simply queue the object
            if (parent.getPoolSize() == parent.getMaximumPoolSize()) return super.offer(o);
            //we have idle threads, just add it to the queue
            if (parent.getSubmittedCount()<(parent.getPoolSize())) return super.offer(o);
             //线程个数小于MaximumPoolSize会创建新的线程。
            //if we have less threads than maximum force creation of a new thread
            if (parent.getPoolSize()<parent.getMaximumPoolSize()) return false;
            //if we reached here, we need to add it to the queue
            return super.offer(o);
        }

    2 Dubbo线程池策略

    Dubbo 提供3种线程池模型即:FixedThreadPool、CachedThreadPool(客户端默认的)、LimitedThreadPool(服务端默认的),从源码可以看出,其默认的队列长度都是0,当队列长度为0 ,其使用是无缓冲的队列SynchronousQueue,当运行线程超过maximumPoolSize则拒绝请求。

    /**
     * 此线程池启动时即创建固定大小的线程数,不做任何伸缩,来源于:<code>Executors.newFixedThreadPool()</code>
     *
     * @author william.liangf
     * @see java.util.concurrent.Executors#newFixedThreadPool(int)
     */
    public class FixedThreadPool implements ThreadPool {
    
        public Executor getExecutor(URL url) {
            String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
            int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
            //默认队列长度为0
            int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
            return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
                    queues == 0 ? new SynchronousQueue<Runnable>() :
                            (queues < 0 ? new LinkedBlockingQueue<Runnable>()
                                    : new LinkedBlockingQueue<Runnable>(queues)),
                    new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
        }
    
    }
    
    /**
     * 此线程池一直增长,直到上限,增长后不收缩。
     *
     * @author <a href="mailto:gang.lvg@alibaba-inc.com">kimi</a>
     */
    public class LimitedThreadPool implements ThreadPool {
    
        public Executor getExecutor(URL url) {
            String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
            int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS);
            int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
                 //默认队列长度为0
            int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
            return new ThreadPoolExecutor(cores, threads, Long.MAX_VALUE, TimeUnit.MILLISECONDS,
                    queues == 0 ? new SynchronousQueue<Runnable>() :
                            (queues < 0 ? new LinkedBlockingQueue<Runnable>()
                                    : new LinkedBlockingQueue<Runnable>(queues)),
                    new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
        }
    
    }
    
    /**
     * 此线程池可伸缩,线程空闲一分钟后回收,新请求重新创建线程,来源于:<code>Executors.newCachedThreadPool()</code>
     *
     * @author william.liangf
     * @see java.util.concurrent.Executors#newCachedThreadPool()
     */
    public class CachedThreadPool implements ThreadPool {
    
        public Executor getExecutor(URL url) {
            String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
            int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS);
            int threads = url.getParameter(Constants.THREADS_KEY, Integer.MAX_VALUE);
                 //默认队列长度为0
            int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
            int alive = url.getParameter(Constants.ALIVE_KEY, Constants.DEFAULT_ALIVE);
            return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS,
                    queues == 0 ? new SynchronousQueue<Runnable>() :
                            (queues < 0 ? new LinkedBlockingQueue<Runnable>()
                                    : new LinkedBlockingQueue<Runnable>(queues)),
                    new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
        }
    
    }

    3 总结

    • 线程池的任务队列本来起缓冲作用,但是如果设置的不合理会导致线程池无法扩容至max,这样无法发挥多线程的能力,导致一些服务响应变慢。
    • 队列长度要看具体使用场景,取决服务端处理能力以及客户端能容忍的超时时间等
    • 建议采用tomcat的处理方式,core与max一致,先扩容到max再放队列,不过队列长度要根据使用场景设置一个上限值,如果响应时间要求较高的系统可以设置为0。
    展开全文
  • C# 使用线程池队列(学习笔记)

    万次阅读 2020-10-15 14:27:27
    使用线程池队列(ThreadPool.QueueUserWorkItem())场景解决方案A.SQLB.控制台代码C.Achievements资源 场景 当初客户要求给自己的营业部和营业所推送邮件(收件人超1000个) 邮件正文是去下载报表WORD(文件大小5...

    使用线程池队列(ThreadPool.QueueUserWorkItem())

    场景

    • 当初客户要求给自己的营业部和营业所推送邮件(收件人超1000个)
    • 邮件正文是去下载报表WORD(文件大小5M以上)数据文件转成HTML
    • 三个附件文件也是要去报表上下载EXCEL(文件大小3M以上)
    • 邮件要在10点之间推送完,但是这里报表的数据是8点以后ETL才刷好(数据刷好的时间不准确)

    解决方案

    • 1000个邮箱用循环去跑肯定慢;就算1分钟10封邮件也发不完;而且也没有这么高的性能
    • 为了提高发送邮件的性能不得不去使用C#线程编程;我在这里使用了线程池这个东西,主要是因为线程池有队列、可以设置线程池中有多个线程一起做任务、线程池可以更好得控制CPU资源自己回收

    A.SQL

    CREATE DATABASE [SendEmailTest]
    
    USE [SendEmailTest]
    GO
    
    CREATE TABLE [dbo].[mailboxUser](
    	[ID] [int] IDENTITY(1,1) NOT NULL,
    	[subject] [nvarchar](120) NULL,
    	[mailBody] [nvarchar](255) NULL,
    	[toEmail] [nvarchar](100) NULL,
    	[toEmailBCC] [nvarchar](100) NULL,
    	[State] [nchar](10) NULL,
    	[Creater] [nvarchar](100) NULL,
    	[CreateTime] [datetime] NULL,
    	[Updater] [nvarchar](100) NULL,
    	[UpdateTime] [datetime] NULL,
     CONSTRAINT [PK_mailboxUser] PRIMARY KEY CLUSTERED 
    (
    	[ID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    
    DECLARE @count INT,@i INT
    SET @count=120
    SET @i=1
    
    WHILE @i<=@count
    BEGIN
    	INSERT INTO [mailboxUser] VALUES 
    	(
    	'今天又是有希望得一天;'+CAST(@i AS NVARCHAR),
    	'今天要把任务做完;'+CAST(@i AS NVARCHAR),
    	'yincongpeng2019@163.com',
    	'',
    	'1',
    	'abel',
    	GETDATE(),
    	null,
    	null
    	)
    	SET @i=@i+1
    END
    

    在这里插入图片描述

    B.控制台代码

    class Program
    {
        private static string userEmail = ConfigHelper.GetConfigStr("userEmail"); //发件人邮箱
        private static string userPswd = ConfigHelper.GetConfigStr("userPswd"); //邮箱帐号密码
        private static string mailServer = ConfigHelper.GetConfigStr("mailServer"); //邮件服务器
        private static string attachFilesPath = ConfigHelper.GetConfigStr("attachFilesPath"); //文件地址
        private static string ServerDataDB = ConfigHelper.GetConfigStr("ServerDataDB");
    
        static void Main(string[] args)
        {
            Console.WriteLine("------------------------------------------------------------------------------1.程序开始");
            Stopwatch watch = new Stopwatch();
            watch.Start(); //开始监视
            ThreadUseAndConstruction();
            //StartSendMail(1,"test","邮件发送测试", "yincongpeng2019@163.com","");
            watch.Stop(); //  停止监视
            Console.WriteLine("------------------------------------------------------------------------------2.程序结束");
            TimeSpan timespan = watch.Elapsed; //  获取当前实例测量得出的总时间
            Console.WriteLine("主线程运行结束;费时:" + timespan.TotalMilliseconds + "(总毫秒数)");
            Console.ReadLine();
        }
    
        /// <summary>
        /// 启动推送邮件线程池方法 2020-10-15 11:03 abel
        /// </summary>
        public static void ThreadUseAndConstruction()
        {
            //1.设置程序在运行时最小线程数和最大线程数
            ThreadPool.SetMinThreads(1, 1); 
            ThreadPool.SetMaxThreads(5, 5); 
    
            //2.查询推送的邮箱用户
            DataTable dt = new DbHelperSQL(ServerDataDB).Query(SelectMailboxUser_SQL).Tables[0];
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                int code = int.Parse(dt.Rows[i]["ID"].ToString());
                string subject = dt.Rows[i]["subject"].ToString();
                string mailBody = dt.Rows[i]["mailBody"].ToString();
                string toEmail = dt.Rows[i]["toEmail"].ToString();
                string toEmailBCC = dt.Rows[i]["toEmailBCC"].ToString();
    
                //3.把推送邮件的方法放入WaitCallback委托
                WaitCallback callback = index =>
                {
                    Stopwatch watch = new Stopwatch();
                    watch.Start(); //开始监视
                    StartSendMail(code, subject, mailBody, toEmail, toEmailBCC);
                    watch.Stop(); //  停止监视
                    TimeSpan timespan = watch.Elapsed; //  获取当前实例测量得出的总时间
                    Console.WriteLine("编号:" + code + "的邮件推送结束;费时:" + timespan.TotalMilliseconds + "(总毫秒数)");
                };
    
                //4.在线程池中加入线程队列
                ThreadPool.QueueUserWorkItem(callback, i);
            }
        }
    
        /// <summary>
        /// 开始推送邮件 2020-10-15 10:30 abel
        /// </summary>
        /// <param name="code">用户邮箱ID</param>
        /// <param name="subject">主题</param>
        /// <param name="mailBody">内容</param>
        /// <param name="toEmail">接收人</param>
        /// <param name="toEmailBCC">抄送人</param>
        public static void StartSendMail(int code, string subject, string mailBody, string toEmail, string toEmailBCC) 
        {
            bool SendState = new EmailHelper(toEmail, toEmailBCC, subject, mailBody, new string[0], userEmail, userPswd, mailServer).SendEmail();
            if (SendState == true) 
                new DbHelperSQL(ServerDataDB).ExecuteSql(UpdateSendMailboxState_SQL, new SqlParameter[] { new SqlParameter("ID", code) });
        }
    
        /// <summary>
        /// 查询推送的邮件用户 2020-10-15 10:52 abel
        /// </summary>
        private const string SelectMailboxUser_SQL = "select * from [dbo].[mailboxUser] where [State]=1";
    
        /// <summary>
        /// 更新邮件推送成功后的状态 2020-10-15 10:50 abel
        /// </summary>
        private const string UpdateSendMailboxState_SQL = "update [dbo].[mailboxUser] set [State]='0',[Updater]='abel_2',[UpdateTime]=getdate() where [ID]=@ID";
    }
    

    C.Achievements

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    资源

    百度网盘链接地址:https://pan.baidu.com/s/1_vJB3tXta42t52f39fAiZQ
    提取码:bhss

    展开全文
  • 线程池队列问题

    2020-10-31 21:49:55
    我们这里的队列都指线程池使用的阻塞队列 BlockingQueue 的实现。 什么是有界队列?就是有固定大小的队列。比如设定了固定大小的 LinkedBlockingQueue,又或者大小为 0,只是在生产者和消费者中做中转用的 ...

    1. 概述

    常用队列

    1. LinkedBlockingQueue:无界队列

    如果不设置大小会导致maximumPoolSize失效

    1. ArrayBlockingQueue:有界队列

    设置队列的大小 如果队列放不下便会开启线程到达maximumPoolSize界限会触发拒绝策略

    1. SynchronousQueue:阻塞队列(不会有等待task>core max)

    没有队列 直接开启线程到达最大线程数(maximumPoolSize)界限会触发拒绝策略

    我们这里的队列都指线程池使用的阻塞队列 BlockingQueue 的实现。

    什么是有界队列?就是有固定大小的队列。比如设定了固定大小的 LinkedBlockingQueue,又或者大小为 0,只是在生产者和消费者中做中转用的 SynchronousQueue。

    什么是无界队列?指的是没有设置固定大小的队列。这些队列的特点是可以直接入列,直到溢出。当然现实几乎不会有到这么大的容量(超过 Integer.MAX_VALUE),所以从使用者的体验上,就相当于 “无界”。比如没有设定固定大小的 LinkedBlockingQueue。

    所以无界队列的特点就是可以一直入列,不存在队列满负荷的现象。

    这个特性,在我们自定义线程池的使用中非常容易出错。而出错的根本原因是对线程池内部原理的不了解。

    比如有这么一个案例,我们使用了无界队列创建了这样一个线程池:

    ExecutorService executor =  new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());1
    

    配置的参数如下:

    • 核心线程数 2
    • 最大线程数 4
    • 空闲线程保活时间 60s
    • 使用无界队列 LinkedBlockingQueue

    然后对这个线程池我们提出一个问题:使用过程中,是否会达到最大线程数 4?

    2. 验证

    我们写了个 Demo 验证一下,设定有 10 个任务,每个任务执行 10s。

    任务的执行代码如下,用 Thread.sleep 操作模拟执行任务的阻塞耗时。

    /**
     * @author lidiqing
     * @since 17/9/17.
     */
    public class BlockRunnable implements Runnable {
        private final String mName;
    
        public BlockRunnable(String name) {
            mName = name;
        }
    
        public void run() {
            System.out.println(String.format("[%s] %s 执行", Thread.currentThread().getName(), mName));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    然后在 main 方法中把这 10 个任务扔进刚刚设计好的线程池中:

     public static void main(String[] args) {
            ExecutorService executor =  new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
            for (int i = 0; i < 10; i++) {
                executor.execute(new BlockRunnable(String.valueOf(i)));
            }
        }123456
    

    结果输出如下:

    [pool-1-thread-2] 1 执行
    [pool-1-thread-1] 0 执行
    [pool-1-thread-2] 2 执行
    [pool-1-thread-1] 3 执行
    [pool-1-thread-1] 5 执行
    [pool-1-thread-2] 4 执行
    [pool-1-thread-2] 7 执行
    [pool-1-thread-1] 6 执行
    [pool-1-thread-1] 8 执行
    [pool-1-thread-2] 9 执行12345678910
    

    发现了什么问题?这里最多出现两个线程。当放开到更多的任务时,也依然是这样。

    3. 剖析

    我们回到线程池 ThreadPoolExecutor 的 execute 方法来找原因。

    public void execute(Runnable command) {
            if (command == null)
                throw new NullPointerException();
            int c = ctl.get();
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                    addWorker(null, false);
            }
            else if (!addWorker(command, false))
                reject(command);
        }12345678910111213141516171819
    

    上面代码的核心就是任务进入等待队列 workQueue 的时机。答案就是,执行 execute 方法时,如果发现核心线程数已满,是会先执行 workQueue.offer(command) 来入列。

    也就是 当核心线程数满了后,任务优先进入等待队列。如果等待队列也满了后,才会去创建新的非核心线程

    所以我们上面设计的线程池,使用了无界队列,会直接导致最大线程数的配置失效。

    可以用一张图来展示整个 execute 阶段的过程:

    运行机制-execute流程

    所以上面的线程池,实际使用的线程数的最大值始终是 corePoolSize ,即便设置了 maximumPoolSize 也没有生效。 要用上 maximumPoolSize ,允许在核心线程满负荷下,继续创建新线程来工作 ,就需要选用有界任务队列。可以给 LinkedBlockingQueue 设置容量,比如 new LinkedBlockingQueue(128) ,也可以换成 SynchronousQueue。

    举个例子,用来做异步任务的 AsyncTask 的内置并发执行器的线程池设计如下:

    public abstract class AsyncTask<Params, Progress, Result> {     
        private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
        // We want at least 2 threads and at most 4 threads in the core pool,
        // preferring to have 1 less than the CPU count to avoid saturating
        // the CPU with background work
        private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
        private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
        private static final int KEEP_ALIVE_SECONDS = 30;
    
        private static final ThreadFactory sThreadFactory = new ThreadFactory() {
            private final AtomicInteger mCount = new AtomicInteger(1);
    
            public Thread newThread(Runnable r) {
                return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
            }
        };
    
        private static final BlockingQueue<Runnable> sPoolWorkQueue =
                new LinkedBlockingQueue<Runnable>(128);
    
        /**
         * An {@link Executor} that can be used to execute tasks in parallel.
         */
        public static final Executor THREAD_POOL_EXECUTOR;
    
        static {
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                    CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                    sPoolWorkQueue, sThreadFactory);
            threadPoolExecutor.allowCoreThreadTimeOut(true);
            THREAD_POOL_EXECUTOR = threadPoolExecutor;
        }
    
        ...
    }
    

    我们可以看到,AsyncTask 的这个线程池设计,是希望在达到核心线程数之后,能够继续增加工作线程,最大达到 CPU_COUNT * 2 + 1 个线程,所以使用了有界队列,限制了任务队列最大数量为 128 个。

    所以使用 AsyncTask 的并发线程池的时候要注意,不适宜短时间同时大量触发大量任务的场景。

    因为当核心线程、任务队列、非核心线程全部满负荷工作的情况下,下一个进来的任务会触发 ThreaPoolExecutor 的 reject 操作,默认会使用 AbortPolicy 策略,抛出 RejectedExecutionException 异常。
    PS:我们这里的队列都指线程池使用的阻塞队列 BlockingQueue 的实现,使用的最多的应该是LinkedBlockingQueue,注意一般情况下要配置一下队列大小,设置成有界队列,否则JVM内存会被撑爆!

    展开全文
  • 线程池队列区别

    2019-12-12 14:24:39
    SynchronousQueue没有容量,是无缓冲等待队列,是一个不存储元素的阻塞队列,会直接将任务交给消费者,必须等队列中的添加元素被消费后才能继续添加新的元素。 拥有公平(FIFO)和非公平(LIFO)策略,非公平侧罗会...
  • 循环体中将任务加入到线程池队列踩坑 问题描述 设置好 如何改变文本的样式 强调文本 强调文本 加粗文本 加粗文本 标记文本 删除文本 引用文本 H2O is是液体。 210 运算结果是 1024. 插入链接与图片 ...
  • 线程池中的队列要求的是阻塞队列,作用主要是当线程池处理任务能力不足时,队列存储多余的任务,从而起到削峰和缓冲的目的。 可以选择的队列种类很多,如何选择合适的队列应用到自己的线程池中?就需要了解他们的优...
  • 本文记录一次线上全链路压测出现的Dubbo线程池队列满的问题。 1 问题描述 线上做全链路压测,其中涉及三个系统,调用关系A-&gt;B-&gt;C,均是dubbo调用。压测的时候C出现CPU满导致服务响应超时的情况,...
  • 通过设置线程池队列大小解决执行容量已满的情况下,主进程还在不断添加任务,会导致内存爆满。
  • Java 线程池 队列

    2014-10-29 23:48:29
    1.使用线程池的目的:
  • 前面学了 Executor 框架,线程池参数,以及基本线程池的使用,今天来学学面试问的核心 – 线程池中的队列队列。在聊聊 java 线程池一文中,简单介绍了几种常用的阻塞队列,但都是一笔带过,接下来的文章会着重讲...
  • 最后一个线程池的阻塞队列了,写完这个线程池篇应该算是结束了。 PriorityBlockingQueue 队列是 JDK1.5 的时候出来的一个阻塞队列
  • 今天介绍另一个线程池的阻塞队列–SynchronousQueue。该队列是在 jdk1.5 的时候出现,和前面写的 LinkedBlockingQueue 和 ArrayBlockingQueue 队列相比,SynchronousQueue 没有数据缓存的空间。 我们先来看看类图: ...
  • } Java的Executors框架提供的定长线程池内部默认使用LinkedBlockingQueue作为任务的容器,这个队列是没有限定大小的,可以无限向里面submit任务。 当线程池处理的太慢的时候,队列里的内容会积累,积累到一定程度就...
  • 队列中的元素都是按照过期时间顺序排序的,队列头部放的是即将过期的元素。该队列中的元素必须实现Delayed接口,getDelay定义了剩余到期时间,compareTo方法定义了元素排序规则。该队列不允许存放null元素。延时...
  • 作者:刘宇。一、什么是LinkedBlockingQueue?二、LinkedBlockingQueue类图三、BlockingQueue的方法四、...链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。
  • Java的Executors框架提供的定长线程池内部默认使用LinkedBlockingQueue作为任务的容器,这个队列是没有限定大小的,可以无限向里面submit任务。当线程池处理的太慢的时候,队列里的内容会积累,积累到一定程度就会...
  • 作者:刘宇。一、什么是ArrayBlockingQueue?...ArrayBlockingQueue是有边界值的,在创建ArrayBlockingQueue时就要确定好该队列的大小,一旦创建,该队列大小不可更改。内部的全局锁是使用的ReentrantLock。
  • 线程池 队列生产者消费者模型实现

    千次阅读 2016-08-23 20:17:40
    static { try { ExecutorService pool = null; try { // 创建一个可重用固定线程数的线程池 pool = Executors.newFixedThreadPool(10); // 创建10个任务
  • (1)如果使用的是无界队列LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为LinkedBlockingQueue 可以近乎认为是一个无穷大的队列,可以无限存放任务 ( 2 ) 如果使用的...
  • java.util.concurrent 使用jdk内置的包实现一个线程池的操作
  • 线程池 1、三大方法 public class Demo { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor();//1.创建单个线程的线程池 ExecutorService ...
  • 通过jdk自带ThreadPoolExecutor线程池+队列 实现优先级方式执行线程任务
  • 主要介绍了java线程池工作队列饱和策略代码示例,涉及线程池的简单介绍,工作队列饱和策略的分析及代码示例,具有一定参考价值,需要的朋友可以了解下。
  • 线程池队列

    2017-09-07 10:24:32
    线程池的作用: 线程池作用就是限制系统中执行线程的数量。  根据系统的环境情况,...若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;
  • Java 线程池等待队列问题

    千次阅读 2019-09-20 15:38:48
    线程池的等待队列最大长度默认为int的最大值,随口默写出来就是2147483647(2^31 -1,高中物理老师说过一句话,记住一些固定的数字可以预判一些问题)。线程池在提交任务时,如果线程池未达到最大线程数,则起线程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 165,912
精华内容 66,364
关键字:

线程池队列