使用Java多线程实现任务分发

Java-分割list并执行多线程任务的工具类 要创建一个用于分割列表并执行多线程任务的工具类,你可以使用 Java 的 ExecutorService 和。线程池创建:使用 Executors.newFixedThreadPool 创建一个固定大小的线程池。列表分割:splitList 方法接收一个列表和一个子列表大小参数,然后将列表分割成多个子列表。任务执行:确保正确处理任务的结果,例如使用 get 方法获取结果或处理异常。创建任务列表,每个任务都是一个 Callable 对象,表示一个计算任务。最后,定义一个方法来提交任务到线程池并执行。 阅读详情

多线程下载由来已久,如 FlashGet、NetAnts 等工具,它们都是依懒于 HTTP 协议的支持(Range 字段指定请求内容范围),首先能读取出请求内容 (即欲下载的文件) 的大小,划分出若干区块,把区块分段分发给每个线程去下载,线程从本段起始处下载数据及至段尾,多个线程下载的内容最终会写入到同一个文件中。

    只研究有用的,工作中的需求:要把多个任务分派给Java的多个线程去执行,这其中就会有一个任务列表指派到线程的策略思考:已知:1. 一个待执行的任务列表,2. 指定要启动的线程数;问题是:每个线程实际要执行哪些任务。

    使用Java多线程实现这种任务分发的策略是:任务列表连续按线程数分段,先保证每线程平均能分配到的任务数,余下的任务从前至后依次附加到线程中——只是数量上,实际每个线程执行的任务都还是连续的。如果出现那种僧多(线程) 粥(任务) 少的情况,实际启动的线程数就等于任务数,一挑一。这里只实现了每个线程各扫自家门前雪,动作快的完成后眼见别的线程再累都是爱莫能助。

    实现及演示代码如下:由三个类实现,写在了一个 Java 文件中:TaskDistributor 为任务分发器,Task 为待执行的任务,WorkThread 为自定的工作线程。代码中运用了命令模式,如若能配以监听器,用上观察者模式来控制 UI 显示就更绝妙不过了,就能实现像下载中的区块着色跳跃的动感了,在此定义下一步的着眼点了。

    代码中有较为详细的注释,看这些注释和执行结果就很容易理解的。main() 是测试方法

package com.alpha.thread;

import java.util.ArrayList;
import java.util.List;

/**
 * 指派任务列表给线程的分发器
 */
public class TaskDistributor {
	
	/**
	 * 测试方法
	 * @param args
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		// 初始化要执行的任务列表
		List taskList = new ArrayList();
		for (int i = 0; i < 100; i++) {
			taskList.add(new Task(i));
		}
		// 设定要启动的工作线程数为 4 个
		int threadCount = 4;
		List[] taskListPerThread = distributeTasks(taskList, threadCount);
		System.out.println("实际要启动的工作线程数:" + taskListPerThread.length);
		for (int i = 0; i < taskListPerThread.length; i++) {
			Thread workThread = new WorkThread(taskListPerThread[i], i);
			workThread.start();
		}
	}

	/**
	 * 把 List 中的任务分配给每个线程,先平均分配,剩于的依次附加给前面的线程 返回的数组有多少个元素 (List) 就表明将启动多少个工作线程
	 * 
	 * @param taskList
	 *            待分派的任务列表
	 * @param threadCount
	 *            线程数
	 * @return 列表的数组,每个元素中存有该线程要执行的任务列表
	 */
	@SuppressWarnings("unchecked")
	public static List[] distributeTasks(List taskList, int threadCount) {
		// 每个线程至少要执行的任务数,假如不为零则表示每个线程都会分配到任务
		int minTaskCount = taskList.size() / threadCount;
		// 平均分配后还剩下的任务数,不为零则还有任务依个附加到前面的线程中
		int remainTaskCount = taskList.size() % threadCount;
		// 实际要启动的线程数,如果工作线程比任务还多
		// 自然只需要启动与任务相同个数的工作线程,一对一的执行
		// 毕竟不打算实现了线程池,所以用不着预先初始化好休眠的线程
		int actualThreadCount = minTaskCount > 0 ? threadCount
				: remainTaskCount;
		// 要启动的线程数组,以及每个线程要执行的任务列表
		List[] taskListPerThread = new List[actualThreadCount];
		int taskIndex = 0;
		// 平均分配后多余任务,每附加给一个线程后的剩余数,重新声明与 remainTaskCount
		// 相同的变量,不然会在执行中改变 remainTaskCount 原有值,产生麻烦
		int remainIndces = remainTaskCount;
		for (int i = 0; i < taskListPerThread.length; i++) {
			taskListPerThread[i] = new ArrayList();
			// 如果大于零,线程要分配到基本的任务
			if (minTaskCount > 0) {
				for (int j = taskIndex; j < minTaskCount + taskIndex; j++) {
					taskListPerThread[i].add(taskList.get(j));
				}
				taskIndex += minTaskCount;
			}
			// 假如还有剩下的,则补一个到这个线程中
			if (remainIndces > 0) {
				taskListPerThread[i].add(taskList.get(taskIndex++));
				remainIndces--;
			}
		}
		// 打印任务的分配情况
		for (int i = 0; i < taskListPerThread.length; i++) {
			System.out.println("线程 "
					+ i
					+ " 的任务数:"
					+ taskListPerThread[i].size()
					+ " 区间["
					+ ((Task) taskListPerThread[i].get(0)).getTaskId()
					+ ","
					+ ((Task) taskListPerThread[i].get(taskListPerThread[i].size() - 1))
							.getTaskId() + "]");
		}
		return taskListPerThread;
	}
}


 

package com.alpha.thread;

/**
 * 要执行的任务,可在执行时改变它的某个状态或调用它的某个操作 例如任务有三个状态,就绪,运行,完成,默认为就绪态 要进一步完善,可为 Task
 * 加上状态变迁的监听器,因之决定UI的显示
 */
class Task {
	public static final int READY = 0;
	public static final int RUNNING = 1;
	public static final int FINISHED = 2;
	@SuppressWarnings("unused")
	private int status;
	// 声明一个任务的自有业务含义的变量,用于标识任务
	private int taskId;

	// 任务的初始化方法
	public Task(int taskId) {
		this.status = READY;
		this.taskId = taskId;
	}

	/**
	 * 执行任务
	 */
	public void execute() {
		// 设置状态为运行中
		setStatus(Task.RUNNING);
		System.out.println("当前线程 ID 是:" + Thread.currentThread().getName()
				+ " | 任务 ID 是:" + this.taskId);
		// 附加一个延时
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 执行完成,改状态为完成
		setStatus(FINISHED);
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public int getTaskId() {
		return taskId;
	}
}


 

package com.alpha.thread;

import java.util.List;

/**
 * 自定义的工作线程,持有分派给它执行的任务列表
 */
class WorkThread extends Thread {
	// 本线程待执行的任务列表,你也可以指为任务索引的起始值
	private List<Task> taskList = null;
	@SuppressWarnings("unused")
	private int threadId;

	/**
	 * 构造工作线程,为其指派任务列表,及命名线程 ID
	 * 
	 * @param taskList
	 *            欲执行的任务列表
	 * @param threadId
	 *            线程 ID
	 */
	@SuppressWarnings("unchecked")
	public WorkThread(List taskList, int threadId) {
		this.taskList = taskList;
		this.threadId = threadId;
	}

	/**
	 * 执行被指派的所有任务
	 */
	public void run() {
		for (Task task : taskList) {
			task.execute();
		}
	}
}


执行结果如下,注意观察每个Java多线程分配到的任务数量及区间。直到所有的线程完成了所分配到的任务后程序结束:

线程 0 的任务数:25 区间[0,24]
线程 1 的任务数:25 区间[25,49]
线程 2 的任务数:25 区间[50,74]
线程 3 的任务数:25 区间[75,99]
实际要启动的工作线程数:4
当前线程 ID 是:Thread-0 | 任务 ID 是:0
当前线程 ID 是:Thread-3 | 任务 ID 是:75
当前线程 ID 是:Thread-1 | 任务 ID 是:25
当前线程 ID 是:Thread-2 | 任务 ID 是:50
当前线程 ID 是:Thread-1 | 任务 ID 是:26
当前线程 ID 是:Thread-3 | 任务 ID 是:76
当前线程 ID 是:Thread-0 | 任务 ID 是:1
当前线程 ID 是:Thread-2 | 任务 ID 是:51


 

上面坦白来只算是基本功夫,贴出来还真见笑了。还有更为复杂的功能。

    像Java多线程的下载工具的确更充分利用了网络资源,而且像 FlashGet、NetAnts 都实现了:假如某个线程下载完了欲先所分配段的内容之后,会帮其他线程下载未完成数据,直到任务完成;或某一下载线程的未完成段区间已经很小了,用不着别人来帮忙时,这就涉及到任务的进一步分配。再如,以上两个工具都能动态增加、减小或中止线程,越说越复杂了,它们原本比这复杂多了,这些实现可能定义各种队列来实现,如未完成任务队列、下载中任务队列和已完成队列等。

 

原文来自:http://java.chinaitlab.com/line/792110.html

java多线程并发executorservice(任务调度)类 主要介绍了线程并发ScheduledExecutorService类,设置 ScheduledExecutorService ,2秒后,在 1 分钟内每 10 秒钟蜂鸣一次 立即下载

相关推荐

《科研伦理与学术规范》期末考试答案2023

26单选(2 分)某学术杂志的评稿人同时是某高校相关专业的硕士生导师,在评判一个稿件的时候,他发现该作者研究的题目很有价值, 他便一边压下这个稿子,一边将稿子的纲要传给自己门下的硕士生, 指导他们使用这个题目独立写出一篇论文,并帮助他们发表在其他期 刊上。D.要善待实验动物,是指在饲养管理和使用实验动物过程中,要采取有效措施,使实验动物免遭不必要的伤害、饥渴、不适、惊恐、折磨、疾病和疼痛,保证动物能够实现自然行为,受到良好的管理与照料,为其提供清洁、舒适的生活环境。张某在压力之下不得不屈从。

Glenseeds的博客 4万+

java 多线程 分发_Java多线程之任务分发

题引:老师有3个同类任务,需要5个同学ABCDE分别都要处理完成。老师分配任务的策略是:每个任务都是随机分配下去的,每个同学拿到任务后都要完成这个任务。像极了做数学题时的套路,这个题目其实就属于Java多线程之任务分发的模式。在实际工作中,如果我们遇到了“要把多个同类任务分派给Java的多个线程去执行”的场景,需要思考如下的问题:(1)待执行的任务列表是什么?(2)需要启动多少Java线程去执行任...

weixin_34416115的博客 950

H医药公司配送中心布局仿真优化

新增2个Source,Source1命名为“货物到达”,用来进行仿真供应商原料到达,Source2命名为“订单到达”,用来进行仿真客户需求订单的到达,如下图是设置两个发生器的具体参数。通过主操作界面上的各个实体工具,如发生器、暂存区、货架、处理器、吸收器等实体工具对初始模型和优化后的方案模型进行仿真建模,建立优化前后的模型图如下图所示。通过下表可以看出,优化前操作员的总运行距离为132.11km,而优化后操作员的总运行距离为128.17km,运行距离缩短,操作员的疲劳强度降低。

m0_72514516的博客 2529

Java:多线程实现任务分发

使用Java多线程实现这种任务分发的策略是:任务列表连续按线程数分段,先保证每线程平均能分配到的任务数,余下的任务从前至后依次附加到线程中--只是数量上,实际每个线程执行的任务都还是连续的。如果出现那种僧多(线程) 粥(任务) 少的情况,实际启动的线程数就等于任务数

一些平时在开发过程中遇到的常见问题,分享给大家 1115

Django 小实例S1 简易学生选课管理系统 —— 〇、初步介绍与演示

python Django实现的一个简易的教务选课系统。 介绍与演示的视频版本已发到我的b站: https://www.bilibili.com/video/BV1er4y1w7ty。 项目已上传到我的github: https://github.com/BigShuang/SimpleStudentCourseManagementSystem。 S1总目录: 〇、初步介绍与演示 一、项目流程梳理与数据库设计 ======================= 大爽歌作,made by big shuang.

大爽老师的博客 5945

机器人视觉实战:用OpenCV搞定手眼标定(附完整C++代码)

本文详细介绍了使用OpenCV实现机器人视觉中的手眼标定技术,包括核心算法、工业场景优化及完整C++代码示例。通过解析坐标系转换问题,提供从数据采集到标定验证的全流程解决方案,帮助开发者在复杂工业环境中实现高精度机械臂与视觉系统的协同作业。

weixin_29306571的博客 484

【Java项目】SpringBoot项目的多文件兼多线程上传下载

SpringBoot实现多文件多线程上传下载

Zhangsama1的博客 3147

PID循迹控制算法

前言  让小车进行循迹最重要的是获取车相对于循迹线的位置,关于循迹模块的原理我已经在之前的一篇博客上讲过,如果大家没看过的话可以点此链接:PID循迹模块原理。 PID循迹原理简介 图1 循迹车寻线行走图示 图2 市场常见循迹传感器  PID循迹的原理我们大致可以用常识性思维去思考下,如图1所示为循迹车寻线行走图示,现在小车要按照中间那条黑线循迹行走,如果车头往左偏则需要控制方向盘让车往右转,车头往又偏则需要让车往左转。但是仅仅只有左转和右转的话,车一到左边就向右转,一到右边就向左转,则车会来回在线左右晃动

Dinvent的博客 7万+

java 多线程数据分发_使用Java多线程实现任务分发

多线程下载由来已久,如 FlashGet、NetAnts 等工具,它们都是依懒于 HTTP 协议的支持(Range 字段指定请求内容范围),首先能读取出请求内容 (即欲下载的文件) 的大小,划分出若干区块,把区块分段分发给每个线程去下载,线程从本段起始处下载数据及至段尾,多个线程下载的内容最终会写入到同一个文件中。只研究有用的,工作中的需求:要把多个任务分派给Java的多个线程去执行,这其中就会有...

weixin_33849758的博客 923

北京绿盟科技安服实习生面经

记一次绿盟校招技术面经历,人生第一次面试,该说不说还是很紧张的,以下是技术面的一些问题,欢迎各位大佬在评论区补充纠正对于面试的问题,都应该自己下来深度去拓展学习,面试官问的问题刚好可以检测我们自己对某个模块的学习情况,借此更好的进行总结和学习。

qq_51690690的博客 3238

FFmpeg + Qt 实现摄像头采集与 MP3 背景音乐 RTSP 推流

在直播或视频监控场景中,我们经常需要将摄像头画面与背景音乐混合后推送到 RTSP 服务器。本文将详细介绍如何使用Qt框架结合摄像头实时采集(Windows 下使用dshow,Linux 使用v4l2视频预览(显示为 QImage)视频 H.264 编码 + RTSP 推流从 MP3 文件读取音频,重采样为 AAC 编码并推流循环播放音频文件解决中文文件路径打开失败的问题文章将剖析每个技术环节的关键代码,并给出完整的类实现。

weixin_45397344的博客 504

java 分发任务_使用Java多线程实现任务分发

多线程下载由来已久,如 FlashGet、NetAnts 等工具,它们都是依懒于 HTTP协议的支持(Range 字段指定请求内容范围),首先能读取出请求内容 (即欲下载的文件) 的大小,划分出若干区块,把区块分段分发给每个线程去下载,线程从本段起始处下载数据及至段尾,多个线程下载的内容最终会写入到同一个文件中。只研究有用的,工作中的需求:要把多个任务分派给Java的多个线程去执行,这其中就会有...

weixin_26736139的博客 999

Floyd (弗洛伊德)算法简述

Floyd在1962年由Robert Floyd以其当前公认的形式出版。算法作为三个嵌套for循环的现代公式首先由Peter Ingerman在1962年描述。Floyd 算法是解决图论问题的比较经典的算法,是解决给定的加权图中顶点间的最短路径的一种算法,可以正确处理有向图的最短路径问题。

慕羽★的博客 2万+

java分发线程任务_使用Java多线程实现任务分发

多线程下载由来已久,如 FlashGet、NetAnts 等工具,它们都是依懒于 HTTP协议的支持(Range 字段指定请求内容范围),首先能读取出请求内容 (即欲下载的文件) 的大小,划分出若干区块,把区块分段分发给每个线程去下载,线程从本段起始处下载数据及至段尾,多个线程下载的内容最终会写入到同一个文件中。只研究有用的,工作中的需求:要把多个任务分派给Java的多个线程去执行,这其中就会有...

weixin_42363154的博客 581

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

上一篇: Java多线程编程总结
下一篇: Java 线程池的原理与实现
JavaAlpha
博客等级 码龄18年 910粉丝 511原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值