线程池(一):阻塞队列

阻塞线程池 阻塞线程池 阻塞线程池 阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池阻塞线程池 立即下载

线程

线程的状态

Java线程在运行的声明周期中可能会处于6种不同的状态,这6种线程状态分别为如下所示。
• New:新创建状态。线程被创建,还没有调用 start 方法,在线程运行之前还有一些基础工作要做。
• Runnable:可运行状态。一旦调用start方法,线程就处于Runnable状态。一个可运行的线程可能正在 运行也可能没有运行,这取决于操作系统给线程提供运行的时间。
• Blocked:阻塞状态。表示线程被锁阻塞,它暂时不活动。
• Waiting:等待状态。线程暂时不活动,并且不运行任何代码,这消耗最少的资源,直到线程调度器 重新激活它。
• Timed waiting:超时等待状态。和等待状态不同的是,它是可以在指定的时间自行返回的。
• Terminated:终止状态。表示当前线程已经执行完毕。导致线程终止有两种情况:第一种就是run方 法执行完毕正常退出;第二种就是因为一个没有捕获的异常而终止了run方法,导致线程进入终止状态。

image

线程创建后,调用 Thread 的 start 方法,开始进入运行状态,
当线程执行wait 方法后, 线程进入等待状态,
进入等待状态的线程需要其他线程通知才能返回运行状态。
超时等待相当于在等待状 态加上了时间限制,如果超过时间限制,则线程返回运行状态。
当线程调用到同步方法时,如果线程没有 获得锁则进入阻塞状态,当阻塞状态的线程获取到锁时则重新回到运行状态。
当线程执行完毕或者遇到意外异常终止时,都会进入终止状态。

创建线程的三种方法
  1. 创建类,继承Thread类,重写run() 方法
  2. 创建类,实现Runnable接口,实现run()方法,然后Thread的构造中,传入此类
  3. 直接创建Thread的实例,调用Start方法
  4. 实现Callable 接口,实现call()方法
public class CallableTest {
    public static class ThreadCallAble implements Callable {

        @Override
        public String call() throws Exception {
            return "hello world";
        }
    }
    public static void main(String args[]) {
        ThreadCallAble mCall = new ThreadCallAble();
        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
        Future mFuture = singleThreadPool.submit(mCall);
        try {
            Log.d("hh", "mFuture.get() = " + mFuture.get());
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

(1)Callable可以在任务接受后提供一个返回值,Runnable无法提供这个功能。
(2)Callable中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常。
(3)运行Callable可以拿到一个Future对象,Future对象表示异步计算的结果,它提供了检查计算是否 完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数的返回值,在这种情况下就可 以使用 Future 来监视目标线程调用 call()方法的情况。但调用 Future的get()方法以获取结果时,当前 线程就会阻塞,直到call()方法返回结果。

线程的终止

当线程的run方法执行完毕,或者在方法中出现没有捕获的异常时,线程将终止。
在Java早期版本中有 一个stop方法,其他线程可以调用它终止线程,但是这个方法现在已经被弃用了。
interrupt 方法可以用来请 求中断线程。当一个线程调用 interrupt 方法时,线程的中断标识位将被置位(中断标识位为true),线程会 不时地检测这个中断标识位,以判断线程是否应该被中断。要想知道线程是否被置位,可以调用 Thread.currentThread().isInterrupted()
调用**Thread.interrupted()**来对中断标识位进行复位。
如果一个线程被阻塞,就无法检测中 断状态。如果一个线程处于阻塞状态,线程在检查中断标识位时如果发现中断标识位为true,则会在阻塞方 法调用处抛出InterruptedException异常,并且在抛出异常前将线程的中断标识位复位,即重新设置为 false。
需要注意的是被中断的线程不一定会终止,中断线程是为了引起线程的注意,被中断的线程可以决定如何 去响应中断。所以如果要终止进程,就需要退出run方法

线程 同步

在多线程应用中,两个或者两个以上的线程需要 共享对同一个数据的存取。
synchronized
volatile

阻塞队列

阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元 素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素
阻塞队列有两个常见的阻塞场景,它们分别是:
(1)当队列中没有数据的情况下,消费者端的所有线程都会被自动阻塞(挂起),直到有数据放入队列。
(2)当队列中填满数据的情况下,生产者端的所有线程都会被自动阻塞(挂起),直到队列中有空的 位置,线程被自动唤醒。
支持以上两种阻塞场景的队列被称为阻塞队列。

BlockingQueue的核心方法 放入数据:
  • offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里。即如果BlockingQueue可以 容纳,则返回true,否则返回false。(本方法不阻塞当前执行方法的线程。)
  • offer(E o,long timeout,TimeUnit unit):可以设定等待的时间。如果在指定的时间内还不能往队列 中加入BlockingQueue,则返回失败。 * put(anObject):将anObject加到BlockingQueue里。如果BlockQueue没有空间,则调用此方法的线程 被阻断,直到BlockingQueue里面有空间再继续。 获取数据:
  • poll(time):取走 BlockingQueue 里排在首位的对象。若不能立即取出,则可以等 time参数规定的时 间。取不到时返回null。
  • poll(long timeout,TimeUnit unit):从BlockingQueue中取出一个队首的对象。如果在指定时间内, 队列一旦有数据可取,则立即返回队列中的数据;否则直到时间超时还没有数据可取,返回失败。
  • take():取走BlockingQueue里排在首位的对象。若BlockingQueue为空,则阻断进入等待状态,直 到 BlockingQueue有新的数据被加入。
  • drainTo():一次性从BlockingQueue获取所有可用的数据对象(还可以指定获取数据的个数)。通 过该方法,可以提升获取数据的效率;无须多次分批加锁或释放锁。
在Java中提供了7个阻塞队列,它们分别如下所示。

• ArrayBlockingQueue:由数组结构组成的 有界 阻塞队列。
• LinkedBlockingQueue:由链表结构组成的 有界 阻塞队列。
• PriorityBlockingQueue:支持优先级排序的 无界 阻塞队列。
• DelayQueue:使用优先级队列实现的 无界 阻塞队列。
• SynchronousQueue:不存储元素的阻塞队列。
• LinkedTransferQueue:由链表结构组成的 无界 阻塞队列。
• LinkedBlockingDeque:由链表结构组成的 双向 阻塞队列

import java.util.concurrent.ArrayBlockingQueue;

/**
 * @author 付影影
 * @desc 阻塞队列
 * @date 2019/10/15
 */
public class BlockingQueueTest {
    private int queueSize = 10;
    private ArrayBlockingQueue<Integer> mArrayBlockingQueue = new ArrayBlockingQueue<>(queueSize);

    public static void main(String[] args) {
        BlockingQueueTest mBlockingQueue = new BlockingQueueTest();
        Consumer consumer = mBlockingQueue.new Consumer();
        Producer producer = mBlockingQueue.new Producer();
        consumer.start();
        producer.start();

    }

    /**
     * 使用阻塞队列实现 生产者和消费者模式,无需考虑同步和线程间同步的问题
     */

    class Consumer extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    mArrayBlockingQueue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class Producer extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    mArrayBlockingQueue.put(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

线程池

在编程中经常会使用线程来异步处理任务,但是每个线程的创建和销毁都需要一定的开销。如果每次 执行一个任务都需要开一个新线程去执行,则这些线程的创建和销毁将消耗大量的资源;并且线程都是“各 自为政”的,很难对其进行控制,更何况有一堆的线程在执行。这时就需要线程池来对线程进行管理

可以通过ThreadPoolExecutor来创建一个线程池,

ThreadPoolExecutor类一共有4个构造方法。其中,拥 有最多参数的构造方法如下所示:
这些参数的作用如下所示。
corePoolSize:核心线程数。默认情况下线程池是空的,只有任务提交时才会创建线程。如果当前运 行的线程数少于corePoolSize,则创建新线程来处理任务;如果等于或者多于corePoolSize,则不再创建。如 果调用线程池的prestartAllcoreThread方法,线程池会提前创建并启动所有的核心线程来等待任务。
maximumPoolSize:线程池允许创建的最大线程数。如果任务队列满了并且线程数小于 maximumPoolSize时,则线程池仍旧会创建新的线程来处理任务。
keepAliveTime:非核心线程闲置的超时时间。超过这个时间则回收。如果任务很多,并且每个任务 的执行事件很短,则可以调大keepAliveTime来提高线程的利用率。另外,如果设置 allowCoreThreadTimeOut属性为true时,keepAliveTime也会应用到核心线程上,
TimeUnit:keepAliveTime参数的时间单位。可选的单位有天(DAYS)、小时(HOURS)、分钟 (MINUTES)、秒(SECONDS)、毫秒(MILLISECONDS)等。
workQueue:任务队列。如果当前线程数大于corePoolSize,则将任务添加到此任务队列中。该任务 队列是BlockingQueue类型的,也就是阻塞队列。
ThreadFactory:线程工厂。可以用线程工厂给每个创建出来的线程设置名字。一般情况下无须设置 该参数。
RejectedExecutionHandler:饱和策略。这是当任务队列和线程池都满了时所采取的应对策略,默认 是AbordPolicy,表示无法处理新任务,并抛出RejectedExecutionException异常。
此外还有3种策略,它们分 别如下。
(1)CallerRunsPolicy:用调用者所在的线程来处理任务。此策略提供简单的反馈控制机制,能够减缓 新任务的提交速度。 (2)DiscardPolicy:不能执行的任务,并将该任务删除。
(3)DiscardOldestPolicy:丢弃队列最近的任务,并执行当前的任务。

线程池执行流程

image

(1)如果线程池中的线程数未达到核心线程数,则创建核心线程处理任务。
(2)如果线程数大于或者等于核心线程数,则将任务加入任务队列,线程池中的空闲线程会不断地从 任务队列中取出任务进行处理。
(3)如果任务队列满了,并且线程数没有达到最大线程数,则创建非核心线程去处理任务。
(4)如果线程数超过了最大线程数,则执行饱和策略

线程池的种类

通过直接或者间接地配置ThreadPoolExecutor的参数可以创建不同类型的ThreadPoolExecutor,其中有 4 种线程池比较常用,它们分别是 FixedThreadPool、CachedThreadPool、SingleThreadExecutor和 ScheduledThreadPool

/**
 *线程池
 */
class ThreadPoolActivity : AppCompatActivity() {
    lateinit var fixThreadPool: ExecutorService
    lateinit var cacheThreadPool: ExecutorService
    lateinit var singleThreadPool: ExecutorService
    lateinit var scheduledThreadPool: ExecutorService
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_thread_pool)
        //固定核心线程和最大线程个数,阻塞队列无界
        fixThreadPool = Executors.newFixedThreadPool(5)
        //没有核心线程 最大线程个数不限制,阻塞队列不存储
        cacheThreadPool = Executors.newCachedThreadPool(object : ThreadFactory {
            var count = 0
            override fun newThread(r: Runnable?): Thread {
                Log.d("hh", "新开的线程: newThreadPool_$count")
                val thread = Thread(r, "newThreadPool_${count++}")
                thread.setUncaughtExceptionHandler { t, e ->
                    //处理非正常的线程中止,多线程中通过trycatch试图捕获线程的异常是不可取的
                    Log.d("hh", t.name)
                    e.printStackTrace()
                }
                return thread
            }
        })

        //核心线程和最大线程个数 只有一个,阻塞队列无界
        singleThreadPool = Executors.newSingleThreadExecutor()
        //定时任务的线程池
        scheduledThreadPool = Executors.newScheduledThreadPool(5)

        tvFixThreadPool.setOnClickListener {
            for (i in 0..10) {
                cacheThreadPoolExecutor(Runnable {
                    Log.d("hh", "i = $i")
                })
            }
        }

        ivDownImg.setOnClickListener {
            //downLoadImg("https://y3.cnliveimg.com:8080/image/itv/2016/1112/7e151ac5d7f84f58a4653e879c973192_161409_100.jpg")
            arrayBlockingQueue()
        }
    }

    /**
     * 线程池 调用
     */
    private fun cacheThreadPoolExecutor(r: Runnable) {
        cacheThreadPool.execute(r)
    }

    /**
     * 下载图片
     */
    private fun downLoadImg(path: String) {
        //它有3个泛型参数,分别为Params、Progress和Result,
        // 其中Params为 参数类型,
        // Progress为后台任务执行进度的类型,
        // Result为返回结果的类型。
        // 如果不需要某个参数,可以将 其设置为Void类型
        val asynctask =
                object : AsyncTask<String, Int, Bitmap>() {

                    //在主线程中执行。一般在任务执行前做准备工作,比如对 UI 做一些标记。
                    override fun onPreExecute() {
                        Log.d("hh", "onPreExecute")
                    }

                    //在线程池中执行。在 onPreExecute方法执行后运行,用来执 行较为耗时的操作。在执行过程中可以调用publishProgress(Progress...values)来更新进度信息。
                    override fun doInBackground(vararg params: String?): Bitmap? {
                        Log.d("hh", "doInBackground")
                        val url = URL(params[0])
                        var bitmap: Bitmap? = null
                        /* val inputStream = url.openStream()
                         val bitmap = BitmapFactory.decodeStream(inputStream)*/

                        //开启连接
                        /* val conn = url.openConnection() as HttpURLConnection
                         //设置连接超时
                         conn.connectTimeout = 5000
                         //设置请求方式
                         conn.requestMethod = "GET"
                         //conn.connect();
                         if (conn.responseCode === 200) {
                             val inputStream = conn.getInputStream()
                             bitmap = BitmapFactory.decodeStream(inputStream)
                             inputStream.close()
                         }
                         conn.disconnect()*/

                        val client = OkHttpClient()
                        //获取请求对象
                        val request = Request.Builder().url(url).build()

                        //获取响应体
                        val body = client.newCall(request).execute().body()

                        //获取流
                        val inputStream = body!!.byteStream()
                        //转化为bitmap

                        return BitmapFactory.decodeStream(inputStream)
                    }

                    //:在主线程中执行。当后台任务执行完成后,它会被执行。 doInBackground方法得到的结果就是返回的result的值。此方法一般做任务执行后的收尾工作,比如更新UI 和数据。
                    override fun onPostExecute(result: Bitmap?) {
                        Log.d("hh", "onPostExecute")
                        ivDownImg.setImageBitmap(result)
                    }

                    //在主线程中执行。当调用 publishProgress(Progress...values)时,此方法会将进度更新到UI组件上
                    override fun onProgressUpdate(vararg values: Int?) {
                        Log.d("hh", "onProgressUpdate")
                    }

                }.execute(path)
    }

    fun arrayBlockingQueue() {
        val arrayBlockingQueue = ArrayBlockingQueue<String>(128)
        arrayBlockingQueue.put("hello")
        arrayBlockingQueue.put("world")
        arrayBlockingQueue.offer("hello")
        arrayBlockingQueue.offer("shadow")
        Log.d("hh", "first = ${arrayBlockingQueue.first()}")
        Log.d("hh", "poll = ${arrayBlockingQueue.poll()}")
    }
}

阻塞队列&线程池 前言 阻塞队列线程池的基础。两者都是面试热点,尤其是线程池。所以我特地花时间学习了下这方面的知识,并做记录。 .阻塞队列 这个其实用的非常多。安卓里面 Handler机制的MessageQueue,我认为就是阻塞队列。 ... 阅读详情

相关推荐

线程池中7种阻塞队列的介绍、区别与选择

1. ArrayBlockingQueue(常用) 基于数组的阻塞队列实现,在 ArrayBlockingQueue 内部,维护了个定长数 组,以便缓存队列中的数据对象,这是个常用的阻塞队列,除了个定长数 组外,ArrayBlockingQueue 内部还保存着两个整形变量,分别标识着队列的 头部和尾部在数组中的位置。 ArrayBlockingQueue 在生产者放入数据和消费者获取数据,都是共用同个 锁对象,由此也意味着两者无法真正并行运行,这点尤其不同于 LinkedBlockingQueue

qq_40306697的博客 9875

线程池设计

这些必须都传给线程池中的线程才行,线程池中的线程从任务中拿取输入数据调用解决方法,最后把输出结果写入,线程池不需要对任务做任何多余的操作!而这个方法函数叫做——回调函数。大体思路是:任务队列不为空就通过条件变量向线程池中的线程发送信号执行任务,如果任务队列为空,则线程池中的线程在cond条件变量下等待。大体思路是: 把信号量的大小设置成任务队列task_queue的大小,这样临界资源的粒度就变小了,实现了生产和消费的解耦。最后线程池被设计成了单例模式,可以保证该线程池全局唯。结构体中的对象包括👇。

潜心钻研技术 934

线程池中常见的阻塞队列

Java 中的包提供了多种阻塞队列,它们在多线程环境下非常有用,特别是在构建线程池时。阻塞队列(BlockingQueue)是种特殊的队列,用于在生产者和消费者线程之间安全地传递数据。线程池中的工作队列通常就是阻塞队列,用于存储待执行的任务。

qq_43012298的博客 1526

浅谈java线程池什么时候触发拒绝策略

浅谈java线程池什么时候触发拒绝策略测试核心线程数是否影响结论 众所周知,线程池提交个任务时先判断核心线程数是否有空余,没有则加入到阻塞队列中。如果阻塞队列也没有空间了,则直接开个线程去执行。 测试 根据这个原理推测,假设核心线程数为0。 根据测试推出结论。 任务数 - 阻塞队列长度 > 最大线程数 触发拒绝策略。 任务数 > 最大线程数 + 阻塞队列长度 触发拒绝策略。 核心线程数是否影响结论 其实最大线程数可以理解为最大允许多少条线程正在执行。由此推导出 核心线程数 +

qq_24817491的博客 2016

线程池常用的阻塞队列有哪些?

线程池常用的阻塞队列有哪些? 文章目录线程池常用的阻塞队列有哪些?1.线程池的内部结构2.阻塞队列3.LinkedBlockingQueue4.SynchronousQueue5.DelayedWorkQueue6.参考 1.线程池的内部结构 线程池内部由四部分组成 第部分是线程池管理器,主要负责管理线程池的创建、销毁、添加任务等管理操作。 第二部分是工作线程,它又分为核心工作线程和非核心工作线程。 第三部分是任务队列,作为种缓冲机制,会将超过核心线程数的任务放到任务队列中,等待执行;由于

谢文峰的博客 9322

Java-五种线程池,四种拒绝策略,三类阻塞队列

Java-五种线程池,四种拒绝策略,三种阻塞队列 三种阻塞队列: BlockingQueue&lt;Runnable&gt; workQueue = null; workQueue = new ArrayBlockingQueue&lt;&gt;(5);//基于数组的先进先出队列,有界 workQueue = new LinkedBlockingQueue&lt;&gt;...

草青工作室 的专栏 2万+

线程池阻塞队列有那些,该如何使用

本文介绍了阻塞队列线程池的使用。阻塞队列在多线程中实现了高效的数据传输,支持自动阻塞和唤醒机制。文章详细讲解了BlockingQueue的核心方法,包括插入、移除和检查操作。在线程池部分,阐述了核心参数配置、工作流程及常见线程池类型(如FixedThreadPool、CachedThreadPool等)。最后强调应避免使用原生Executors创建线程池,以防止OOM风险,推荐自定义ThreadPoolExecutor,合理设置队列容量和拒绝策略。通过合理应用这些并发工具,可以构建高质量的多线程程序。

qq_52445645的博客 1100

Java多线程】7——阻塞队列&线程池

在《阿里巴巴Java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显式的创建线程,这样方面是线程的创建更加规范,可以合理控制开辟线程的数量;另方面线程的细节管理交给线程池处理,优化了资源的开销。同时线程池不允许使用Executors去创建,而要通过方式,这方面是由于JDK 中 Executor 框架虽然提供了如等创建线程池的方法,但都有其局限性,不够灵活;使用有助于大家明确线程池的运行规则,创建符合自己的业务场景需要的线程池,避免资源耗尽的风险。

一棵灬大树的博客 2463

阻塞队列线程池原理

阻塞队列:当队列已满的时候,向队列中添加元素的操作会被阻塞;当队列为空的时候,从队列中取元素的操作会被阻塞。Java 中用 BlockingQueue 接口表示阻塞队列。BlockingQueue 接口作为 Queue 的子接口,主要作用不是作为容器,而是作为线程同步的工具。它的特征是。有界是指队列存放的数量有上限,到达上限后再向队列中存放元素就会被阻塞。这个“无界”肯定也是有限制的,当容量过大时会造成 OOM。

tmacfrank 2057

线程池阻塞队列

Java线程池面试题,包括线程池的使用、原理 线程池中要使用阻塞队列,那么延申下——阻塞队列的基本概念、底层源码

cloud_fly的博客 1429

阻塞队列线程池

本篇将详细介绍阻塞队列线程池

qq_66292058的博客 1317

线程池中为什么要使用阻塞队列

转载自:https://blog.csdn.net/qq_35181209/article/details/77921029 在线程池中活跃线程数达到corePoolSize时,线程池将会将后续的task提交到BlockingQueue中,为什么这样设计呢? 原因为: 线程池创建线程需要获取mainlock这个全局锁,影响并发效率,阻塞队列可以很好的缓冲。 如果新任务的到达速率超过了线程池的处理速率,那么新到来的请求将累加起来,这样的话将耗尽资源。 在个task提交到线程池时,假设可以被线程池

qq_34851243的博客 9156

Java线程池中的阻塞队列类型

Java线程池中,阻塞队列是存储待执行任务的核心组件。以下是三种常用的阻塞队列类型,它们各自具有独特的特点和适用场景。

✨ 欢迎来到【Seal ^_^ 的CSDN博客】!✨ 4757

线程池常用的阻塞队列有哪些

线程池常用的阻塞队列包括:1. ArrayBlockingQueue(基于数组的有界队列);2. LinkedBlockingQueue(基于链表的可选有界/无界队列);3. SynchronousQueue(不存储元素,直接传递任务);4. PriorityBlockingQueue(支持优先级排序的无界队列)。此外,ScheduledThreadPoolExecutor使用延迟队列DelayedWorkQueue处理定时任务。

weixin_46084191的博客 831

线程池阻塞队列:告别资源耗尽,拥抱优雅并发!

线程池阻塞队列:打造流畅高效的并发系统!😀

qq_56158663的博客 1737

java多线程:线程池阻塞队列

线程池定义和使用 jdk 1.5 之后就引入了线程池。 1.1 定义 从上面的空间切换看得出来,线程是稀缺资源,它的创建与销毁是个相对偏重且耗资源的操作,而Java线程依赖于内核线程,创建线程需要进行操作系统状态切换。为避免资源过度消耗需要设法重用线程执行多个任务。线程池就是个线程缓存,负责对线程进行统分配、调优与监控。(数据库连接池也是样的道理) 什么时候使用线程池? 单个任务处理时间比较短;需要处理的任务数量很大。 线程池优势? 重用存在的线程,减少线程创建、消亡的开销,提高性能、提高响应

LifeGoesOn 4365
上一篇: 站在巨人肩上操作CAS(三):原子操作类的正确使用实战
下一篇: 线程池(二):线程池底层实现分析
斯音
博客等级 码龄6年 47粉丝 120原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值