导航:首页 > 编程语言 > java工作队列的使用

java工作队列的使用

发布时间:2025-07-11 15:31:17

java 线程池 工作队列是如何工作的

使用线程池的好处

1、降低资源消耗

可以重复利用已创建的线程降低线程创建和销毁造成的消耗。

2、提高响应速度

当任务到达时,任务可以不需要等到线程创建就能立即执行。

3、提高线程的可管理性

线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控

线程池的工作原理

首先我们看下当一个新的任务提交到线程池之后,线程池是如何处理的

1、线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则执行第二步。

2、线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里进行等待。如果工作队列满了,则执行第三步

3、线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务

线程池饱和策略

这里提到了线程池的饱和策略,那我们就简单介绍下有哪些饱和策略:

AbortPolicy

为Java线程池默认的阻塞策略,不执行此任务,而且直接抛出一个运行时异常,切记ThreadPoolExecutor.execute需要try catch,否则程序会直接退出。

DiscardPolicy

直接抛弃,任务不执行,空方法

DiscardOldestPolicy

从队列里面抛弃head的一个任务,并再次execute 此task。

CallerRunsPolicy

在调用execute的线程里面执行此command,会阻塞入口

用户自定义拒绝策略(最常用)

实现RejectedExecutionHandler,并自己定义策略模式

下我们以ThreadPoolExecutor为例展示下线程池的工作流程图

3.jpg

关键方法源码分析

我们看看核心方法添加到线程池方法execute的源码如下:

// //Executes the given task sometime in the future. The task //may execute in a new thread or in an existing pooled thread. // // If the task cannot be submitted for execution, either because this // executor has been shutdown or because its capacity has been reached, // the task is handled by the current {@code RejectedExecutionHandler}. // // @param command the task to execute // @throws RejectedExecutionException at discretion of // {@code RejectedExecutionHandler}, if the task // cannot be accepted for execution // @throws NullPointerException if {@code command} is null // public void execute(Runnable command) { if (command == null) throw new NullPointerException(); // // Proceed in 3 steps: // // 1. If fewer than corePoolSize threads are running, try to // start a new thread with the given command as its first // task. The call to addWorker atomically checks runState and // workerCount, and so prevents false alarms that would add // threads when it shouldn't, by returning false. // 翻译如下: // 判断当前的线程数是否小于corePoolSize如果是,使用入参任务通过addWord方法创建一个新的线程, // 如果能完成新线程创建exexute方法结束,成功提交任务 // 2. If a task can be successfully queued, then we still need // to double-check whether we should have added a thread // (because existing ones died since last checking) or that // the pool shut down since entry into this method. So we // recheck state and if necessary roll back the enqueuing if // stopped, or start a new thread if there are none. // 翻译如下: // 在第一步没有完成任务提交;状态为运行并且能否成功加入任务到工作队列后,再进行一次check,如果状态 // 在任务加入队列后变为了非运行(有可能是在执行到这里线程池shutdown了),非运行状态下当然是需要 // reject;然后再判断当前线程数是否为0(有可能这个时候线程数变为了0),如是,新增一个线程; // 3. If we cannot queue task, then we try to add a new // thread. If it fails, we know we are shut down or saturated // and so reject the task. // 翻译如下: // 如果不能加入任务到工作队列,将尝试使用任务新增一个线程,如果失败,则是线程池已经shutdown或者线程池 // 已经达到饱和状态,所以reject这个他任务 // int c = ctl.get(); // 工作线程数小于核心线程数 if (workerCountOf(c) < corePoolSize) { // 直接启动新线程,true表示会再次检查workerCount是否小于corePoolSize if (addWorker(command, true)) return; c = ctl.get(); } // 如果工作线程数大于等于核心线程数 // 线程的的状态未RUNNING并且队列notfull if (isRunning(c) && workQueue.offer(command)) { // 再次检查线程的运行状态,如果不是RUNNING直接从队列中移除 int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) // 移除成功,拒绝该非运行的任务 reject(command); else if (workerCountOf(recheck) == 0) // 防止了SHUTDOWN状态下没有活动线程了,但是队列里还有任务没执行这种特殊情况。 // 添加一个null任务是因为SHUTDOWN状态下,线程池不再接受新任务 addWorker(null, false); } // 如果队列满了或者是非运行的任务都拒绝执行 else if (!addWorker(command, false)) reject(command); }

㈡ 《Java面向对象编程》导读-Deque双向队列的用法

在Java面向对象编程的世界中,Queue接口的单向特性并不能满足所有场景的需求,这时就引出了其子接口Deque,专为双向操作而设计。双向队列的特点在于允许在队列的前端(头部)和后端(尾部)进行元素的添加和删除。

首先,Deque提供了向队列两端进行操作的方法:

- `addFirst(E element)` 和 `addLast(E element)`:用于在队列头部和尾部添加元素。当队列已满时,这两个方法会抛出IllegalStateException。

- `offerFirst(E element)` 和 `offerLast(E element)`:类似添加,但若队列满,返回false而非抛出异常。

接下来,双向队列也支持从两端删除元素:

- `removeFirst()` 和 `removeLast()`:移除队列头部和尾部的元素。队列为空时,这两个方法会抛出NoSuchElementException。

- `pollFirst()` 和 `pollLast()`:尝试移除元素,如果队列为空则返回null。

获取元素但不删除也有所谓的方法:

- `getFirst()` 和 `getLast()`:获取队列头部和尾部的元素,空队列时抛出NoSuchElementException。

- `peekFirst()` 和 `peekLast()`:查看队列前端和后端的元素,但不改变队列状态。

LinkedList和ArrayDeque这两个类都实现了Deque接口,例如在例程1的DequeTester类中,我们能看到实际操作双向队列的实例。程序首先在两端添加元素,接着遍历队列,最后删除尾部元素。运行该类,我们可以看到预期的输出结果。

以上内容摘自孙卫琴的经典Java著作《Java面向对象编程》,通过这些方法,我们可以灵活地在队列的前后两端进行操作,极大地扩展了队列的实用功能。

阅读全文

与java工作队列的使用相关的资料

热点内容
平板电脑无法打开文件 浏览:718
win10如何强制重命名文件 浏览:204
java集合随机打乱顺序 浏览:805
qq怎么解绑app 浏览:995
苹果设备优盘考文件 浏览:662
java项目部署与测试 浏览:728
个人微信号和公众平台 浏览:988
微信显示网络不可用 浏览:478
现实编程怎么敲键盘 浏览:950
怎么做招标文件 浏览:543
黑苹果macminidiy 浏览:105
系统暂时删除应用程序 浏览:400
怎么更改qq邮箱的账号和密码 浏览:947
电视剧周边是什么网络用语 浏览:130
网络信号怎么来的 浏览:802
win10文件默认颜色 浏览:713
安卓的荣耀战区 浏览:621
使excel文件损坏的原因 浏览:746
有个搜题网站叫知什么 浏览:17
川剧迷app在哪里下载 浏览:677

友情链接