当前位置: 首页 > news >正文

07-多线程案例-任务调度

任务调度

挑战:在并发环境中,如何合理调度任务以提高效率和响应速度。

在并发环境中,合理调度任务以提高效率和响应速度是非常重要的。可以通过使用线程池(如 ExecutorService)和合适的任务队列(如 BlockingQueue)来管理任务的调度。下面给出几个使用场景和代码实例,帮助展示如何通过这些机制提高任务调度效率。

使用场景

1. 任务数量不确定时:
  • 如果任务的数量和执行时间都不确定,使用线程池和 BlockingQueue 可以有效管理任务的生产和消费,避免线程过多导致的资源浪费,同时保证任务的按顺序执行。
2. 高并发任务的处理:
  • 在需要处理大量并发请求时(如 Web 服务器或异步任务处理),通过线程池和任务队列能够高效地调度和处理这些任务。
3. 生产者-消费者问题:
  • 在多线程环境下,使用 BlockingQueue 来实现生产者和消费者模式,可以确保生产者在任务队列满时等待,消费者在队列为空时等待,从而避免了资源的浪费和任务的丢失。

1. 使用 ExecutorServiceBlockingQueue 管理任务队列

示例 1:生产者-消费者模式

在该示例中,生产者线程将任务放入 BlockingQueue,而消费者线程则从队列中取出任务并执行。

import java.util.concurrent.*;class ProducerConsumerExample {private static final int QUEUE_CAPACITY = 10;public static void main(String[] args) throws InterruptedException {BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);// 创建一个线程池来处理任务ExecutorService executor = Executors.newFixedThreadPool(4);// 启动生产者线程executor.submit(new Producer(queue));// 启动消费者线程executor.submit(new Consumer(queue));// 等待一段时间后关闭线程池Thread.sleep(10000);executor.shutdown();}
}class Producer implements Runnable {private final BlockingQueue<Integer> queue;public Producer(BlockingQueue<Integer> queue) {this.queue = queue;}@Overridepublic void run() {try {int i = 0;while (true) {queue.put(i); // 将任务放入队列System.out.println("生产者生产任务: " + i);i++;Thread.sleep(500); // 模拟任务生产时间}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}class Consumer implements Runnable {private final BlockingQueue<Integer> queue;public Consumer(BlockingQueue<Integer> queue) {this.queue = queue;}@Overridepublic void run() {try {while (true) {Integer task = queue.take(); // 从队列中取出任务System.out.println("消费者消费任务: " + task);Thread.sleep(1000); // 模拟任务消费时间}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}

说明:

  • 使用 ArrayBlockingQueue 作为任务队列,生产者不断向队列中添加任务,消费者则从队列中取任务并执行。
  • 线程池管理生产者和消费者线程,避免了频繁创建线程带来的性能损耗。

2. 处理高并发任务

示例 2:高并发任务处理

在这个示例中,我们创建一个线程池并提交大量的任务,线程池根据系统资源自动分配线程,避免了线程过多导致的性能瓶颈。

import java.util.concurrent.*;class HighConcurrencyExample {public static void main(String[] args) throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池// 提交大量任务for (int i = 0; i < 100; i++) {int taskId = i;executor.submit(() -> {System.out.println("任务 " + taskId + " 开始执行,线程:" + Thread.currentThread().getName());try {Thread.sleep(100); // 模拟任务执行} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println("任务 " + taskId + " 执行完毕");});}// 关闭线程池executor.shutdown();}
}

说明:

  • 通过创建一个固定大小的线程池 Executors.newFixedThreadPool(10),我们限制了并发线程数为 10。
  • 线程池会根据任务的数量和执行时间合理调度线程,有效避免了线程过多导致的上下文切换和资源浪费。

3. 定时任务调度

示例 3:定时任务调度

使用 ScheduledExecutorService 来定期执行任务。例如,定时检查系统健康状况或者定期清理缓存。

import java.util.concurrent.*;class ScheduledTaskExample {public static void main(String[] args) {ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); // 创建一个定时任务线程池// 定时任务,每隔 2 秒执行一次executor.scheduleAtFixedRate(() -> {System.out.println("定时任务执行,时间:" + System.currentTimeMillis());}, 0, 2, TimeUnit.SECONDS);// 运行 10 秒后关闭线程池try {Thread.sleep(10000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}executor.shutdown();}
}

说明:

  • 使用 scheduleAtFixedRate 方法安排一个定时任务,每隔 2 秒执行一次。
  • 适用于需要定期执行任务的场景,如健康检查、日志清理等。

总结

  • ExecutorService 使得任务的调度更加高效,减少了线程创建和销毁的开销。
  • BlockingQueue 用于生产者-消费者模式,合理控制任务的流入和流出,避免了资源浪费。
  • ScheduledExecutorService 可以用来执行定时任务,适合需要周期性执行的场景。

通过合理使用线程池和任务队列,能够大大提高并发环境下任务的处理效率和响应速度。

http://www.xdnf.cn/news/661465.html

相关文章:

  • NoteGen 如何使用 AI 进行记录
  • set和map简单模拟实现
  • TCP 三次握手过程详解
  • 【Java学习笔记】抽象类
  • 时间的基本概念及相关技术
  • 通用寄存器 专用寄存器
  • 大模型训练中的GPU作用解析
  • 项目三 - 任务8:实现词频统计功能
  • 基于Geotools的Worldpop世界人口tif解析-以中国2020年数据为例
  • 北京大学肖臻老师《区块链技术与应用》公开课:02-BTC-密码学原理
  • Excel快捷键大全
  • 深入理解Java装饰器模式:动态扩展对象功能的优雅之道
  • USB设备状态
  • pyhton基础【5】循环
  • uniapp 小说成品源码
  • Python爬虫实战:研究Selenium框架相关技术
  • NAT、代理服务、内网穿透
  • Python训练营打卡Day37
  • 经典文献阅读之--RT-Grasp(通过MLLM进行推理调优的机器人抓取)
  • 如何设计ES的冷热数据分离架构?Elasticsearch 集群如何实现高可用?如何避免脑裂问题?如果出现脑裂如何恢复?
  • 6.1 Q1|广州医科大学GBD发文 | 良性前列腺增生与合并症之间的相关性
  • mysql ACID 原理
  • OpenCV CUDA模块图像过滤------创建一个 Sobel 滤波器函数createSobelFilter()
  • 高并发下使用防重表做防重案例
  • Linux 常用操作步骤
  • ubantu给github配置ssh
  • Unity—lua基础语法
  • MyBatis-Plus 中 的动态SQL 片段(sqlSegment)讲解
  • 速卖通,国际站测评补单,如何平衡效率和安全
  • C++ ——new和malloc的区别(详细)