`
vtrtbb
  • 浏览: 359947 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

多线程执行任务

    博客分类:
  • java
 
阅读更多

只研究有用的,工作中的需求:要把多个任务分派给多个线程去执行,这其中就会有一个任务列表指派到线程的策略思考:已知:1. 一个待执行的任务列表,2. 指定要启动的线程数;问题是:每个线程实际要执行哪些任务。
  策略是:任务列表连续按线程数分段,先保证每线程平均能分配到的任务数,余下的任务从前至后依次附加到线程中--只是数量上,实际每个线程执行的任务都还是连续的。如果出现那种僧多(线程) 粥(任务) 少的情况,实际启动的线程数就等于任务数,一挑一。这里只实现了每个线程各扫自家门前雪,动作快的完成后眼见别的线程再累都是爱莫能助。
  实现及演示代码如下:由三个类实现,写在了一个 java 文件中:TaskDistributor 为任务分发器,Task 为待执行的任务,WorkThread 为自定的工作线程。代码中运用了命令模式,如若能配以监听器,用上观察者模式来控制 UI 显示就更绝妙不过了,就能实现像下载中的区块着色跳跃的动感了,在此定义下一步的着眼点了。
  代码中有较为详细的注释,看这些注释和执行结果就很容易理解的。main() 是测试方法

 

package com.unmi.common;
  import java.util.ArrayList;
  import java.util.List;
  public class TaskDistributor {
  /**
  * 测试方法
  * @param args
  */
  public static void main(String[] args) {
  //初始化要执行的任务列表
  List taskList = new ArrayList();
  for (int i = 0; i < 108; i++) {
  	taskList.add(new Task(i));
  }
  //设定要启动的工作线程数为 5 个
  int threadCount = 5;
  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 列表的数组,每个元素中存有该线程要执行的任务列表
  */
  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() + " 区间["
  + taskListPerThread[i].get(0).getTaskId() + ","
  + taskListPerThread[i].get(taskListPerThread[i].size() - 1).getTaskId() + "]");
  }
  return taskListPerThread;
  }
  }
  /**
  * 要执行的任务,可在执行时改变它的某个状态或调用它的某个操作
  * 例如任务有三个状态,就绪,运行,完成,默认为就绪态
  * 要进一步完善,可为 Task 加上状态变迁的监听器,因之决定UI的显示
  */
  class Task {
  public static final int READY = 0;
  public static final int RUNNING = 1;
  public static final int FINISHED = 2;
  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;
  }
  }

/**
  * 自定义的工作线程,持有分派给它执行的任务列表
  */
  class WorkThread extends Thread {
  //本线程待执行的任务列表,你也可以指为任务索引的起始值
  private List taskList = null;
  private int threadId;
  /**
  * 构造工作线程,为其指派任务列表,及命名线程 ID
  * @param taskList 欲执行的任务列表
  * @param threadId 线程 ID
  */
  public WorkThread(List taskList,int threadId) {
  this.taskList = taskList;
  this.threadId = threadId;
  }
  /**
  * 执行被指派的所有任务
  */
  public void run() {
  for (Task task : taskList) {
  task.execute();
  }
  }
  }

 

执行结果如下,注意观察每个线程分配到的任务数量及区间。直到所有的线程完成了所分配到的任务后程序结束:
  线程 0 的任务数:22 区间[0,21]
  线程 1 的任务数:22 区间[22,43]
  线程 2 的任务数:22 区间[44,65]
  线程 3 的任务数:21 区间[66,86]
  线程 4 的任务数:21 区间[87,107]
  实际要启动的工作线程数:5
  当前线程 ID 是:Thread-0 | 任务 ID 是:0
  当前线程 ID 是:Thread-1 | 任务 ID 是:22
  当前线程 ID 是:Thread-2 | 任务 ID 是:44
  当前线程 ID 是:Thread-3 | 任务 ID 是:66
  当前线程 ID 是:Thread-4 | 任务 ID 是:87
  当前线程 ID 是:Thread-0 | 任务 ID 是:1
  当前线程 ID 是:Thread-1 | 任务 ID 是:23
  当前线程 ID 是:Thread-2 | 任务 ID 是:45

分享到:
评论

相关推荐

    易语言多线程执行任务例程

    在这个“易语言多线程执行任务例程”中,我们将深入探讨如何在易语言中利用多线程技术来提升程序的运行效率和并发能力。 多线程是现代计算机编程中的一个重要概念,它允许一个程序同时执行多个任务,从而充分利用...

    多线程执行任务具体实现

    本篇文章将深入探讨多线程执行任务的具体实现方式。 一、线程的概念与优势 线程是操作系统分配CPU时间的基本单元,一个进程可以包含一个或多个线程。相比于单线程,多线程能充分利用多核处理器资源,减少程序等待I/...

    乐玩8.172游戏自动登录多线程执行任务易语言源码逍遥Q缘

    乐玩8.172游戏自动登录多线程执行任务的易语言源码,是针对特定游戏版本(乐玩8.172)设计的一种自动化工具。这种工具的主要功能是帮助玩家实现游戏内的自动化操作,比如自动登录、执行师门任务、宝图任务、帮派任务...

    多线程并发执行任务

    在IT领域,多线程并发执行任务是一种常见的优化策略,特别是在服务器端开发、实时系统以及高性能计算中。本文将深入探讨多线程并发执行任务的相关知识点,并基于提供的`MyThread.java`文件,来分析和理解如何在Java...

    易语言-易语言多线程执行任务例程

    在“易语言-易语言多线程执行任务例程”中,我们可以学习到如何在易语言环境中创建和管理多线程。多线程技术的核心在于并发执行,通过合理分配系统资源,使得程序的各个部分可以并行工作,从而减少整体的等待时间。 ...

    易语言源码多线程多任务下载软件.rar

    而多线程则允许程序同时执行多个任务,每个任务在独立的线程中运行,互不干扰。在下载软件中,多线程可以将大文件分割成多个小部分,分别由不同的线程下载,显著提升了下载速度。 本软件的多任务处理功能则意味着...

    多线程并行执行,汇总结果

    在IT行业中,多线程并行执行是一种常见的优化策略,特别是在处理大数据量或者需要高性能计算的任务时。"CountDownLatch" 和 "Thread" 是Java编程语言中实现多线程并行执行的关键工具,它们有助于提高程序的运行效率...

    vb模拟多线程执行大任务

     声明BigJob 对 像(包括事件),创建BigJob 的实 例,通知对像执行任务,在对像的“ 开 始”事件中给用户一些提示,数字时钟”在不间断地显示当前时间。  不足之处:终止任务(关闭窗体)时 Activex.exe 部件需要...

    C#多线程执行

    本篇文章将深入探讨C#中的多线程执行,并结合“TaskSortRelationArrange”这个文件名,推测其可能涉及到的任务排序与关系安排。 一、C#多线程基础 C#中的多线程主要依赖于System.Threading命名空间,其中Thread类是...

    c# 多线程 异步进度条

    总结起来,"c# 多线程 异步进度条"涉及如何在C#中利用多线程执行任务,同时通过异步机制和进度条组件,向用户展示任务执行的实时进度。正确实现这一功能需要理解多线程的创建与同步,异步编程的原理,以及UI线程安全...

    winform 多线程 多任务管理

    多线程则允许我们同时执行多个任务,每个任务在一个独立的线程上运行,从而提高效率并保持UI的流畅。 在Winform中,我们可以使用`System.Threading`命名空间中的类来创建和管理线程。最常用的是`Thread`类,它代表...

    计算多线程环境下执行任务时间1

    4. 工作线程执行任务,完成后调用`done.countDown()`,减少`done`的计数。 5. 主线程等待所有任务完成(`done.await()`返回),然后计算并返回总执行时间。 这个设计巧妙地利用了`CountDownLatch`来确保所有线程在...

    多线程计数实现多线程执行后再执行主线程

    ### 多线程计数实现多线程执行后再执行主线程 #### 一、知识点概述 本文将深入探讨如何利用`CountDownLatch`机制来确保多个子线程完成各自的任务后,再让主线程继续执行的方法。这种方法在项目开发中非常实用,...

    易语言源代码_多线程多任务下载软件.zip

    在这个“易语言源代码_多线程多任务下载软件.zip”压缩包中,包含了一个使用易语言编写的多线程多任务下载软件的源代码,主要文件名为“多线程多任务下载软件.e”。 多线程技术在软件开发中扮演着重要角色,尤其是...

    Go-提供多线程定时任务

    在Go语言中,实现多线程定时任务是一个常见的需求,特别是在服务器端编程或者后台任务处理中。Go语言的并发模型是基于CSP(Communicating Sequential Processes)理论的,通过goroutine和channel来实现轻量级线程和...

    多线程任务控制实例代码

    主要实现了,多个线程任务在同时执行的情况下,保证线程任务顺序的问题。更通俗来说,就是保证Thread1一定在thread2,thread3之后才能执行。另外,代码里我写了详细的注释,和测试的效果,绝对让你能看懂。还有我传的...

    Qt 之多线程处理多任务

    在Qt框架中,多线程处理多任务是提高应用程序性能和响应能力的重要手段。Qt提供了丰富的多线程支持,使得开发者能够充分利用现代计算机的多核处理器资源,避免UI线程因执行耗时操作而导致的界面假死问题。本文将深入...

    IOS-多线程多任务下载

    在iOS中,多线程是指在一个应用程序中同时执行多个线程。主线程主要负责UI更新,保持用户界面的流畅性;而子线程则用于处理耗时操作,如网络请求和数据处理。多线程能够有效利用CPU资源,提高程序运行效率。 多任务...

    java多线程之A线程等B、C线程都执行完在执行的结果示例

    在这个场景中,我们关注的是一个特定的多线程问题:A线程需要等待B线程和C线程执行完毕后再开始执行,同时避免A线程无休止地检查状态导致的CPU空耗。 首先,我们需要理解Java中线程间的协作机制。Java提供了多种...

Global site tag (gtag.js) - Google Analytics