`

把多个任务分派给多个线程去执行

    博客分类:
  • Java
阅读更多

要把多个任务分派给Java的多个线程去执行,这其中就会有一个任务列表指派到线程的策略思考:已知:1. 一个待执行的任务列表,2. 指定要启动的线程数;问题是:每个线程实际要执行哪些任务。
使用Java多线程实现这种任务分发的策略是:任务列表连续按线程数分段,先保证每线程平均能分配到的任务数,余下的任务从前至后依次附加到线程中--只是数量上,实际每个线程执行的任务都还是连续的。如果出现那种僧多(线程) 粥(任务) 少的情况,实际启动的线程数就等于任务数。这里只实现了每个线程各扫自家门前雪,动作快的完成后眼见别的线程再累都是爱莫能助。
实现及演示代码如下:由三个类实现,写在了一个 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
0
分享到:
评论

相关推荐

    实验4 线程编程实验.doc

    线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。 2. 线程的创建方法 在Java中,线程可以通过继承Thread类或实现Runnable接口来创建。Thread类提供了start()方法来启动线程,而Runnable接口提供了...

    20多任务和多线程[定义].pdf

    - **deadlock**:死锁,多个线程因互相等待对方释放资源而无法继续执行的情况。 ### 线程同步机制 为了防止多个线程同时操作同一数据导致数据不一致,线程同步机制是必须的。常见的同步机制有: - **互斥锁...

    多线程客户端

    在IT领域,多线程客户端是一种能够同时执行多个任务或操作的软件应用。这个概念尤其在网络编程中显得尤为重要,因为多线程可以显著提高应用程序的效率和响应性。在这个场景下,我们聚焦于"多线程的FTP客户端",这...

    C#_细说多线程(上下)

    PLINQ能够自动地将查询操作分解到多个线程上执行,从而提高查询效率。 #### 八、计时器与锁 - **计时器**:`System.Threading.Timer` 类可用于实现定时任务。与`System.Timers.Timer`不同的是,前者更加高效且适合...

    java 多线程

    - **wait() 和 notify() 方法**:这些方法是`Object`类的一部分,用于同步多个线程。`wait()`方法使当前线程进入等待状态,直到其他线程调用`notify()`或`notifyAll()`唤醒它。 - **join() 方法**:允许一个线程等待...

    winsock多线程实例

    6. **线程同步**:为了防止多个线程同时访问共享资源,如套接字,我们需要使用互斥量、事件对象或临界区等同步原语来确保线程安全。 7. **线程池管理**:线程池的管理包括线程的创建、任务分配、线程的复用和回收。...

    英特尔多核多线程技术

    如果一个进程包含了多个线程,那么这个进程就能够同时执行多个任务。这不仅提高了处理器的利用效率,还极大地增强了系统的响应能力和处理能力。 #### 三、多核多线程技术的应用 多核多线程技术的应用范围非常广泛...

    VC++多线程与网络

    每个进程拥有独立的地址空间,可以包含一个或多个线程。 - **线程**:线程是进程中的实际运行单位,是CPU调度和分派的基本单位。在同一进程中的线程共享进程的资源,如内存空间、文件句柄等,因此线程之间的通信比...

    TBB多线程库

    2. **任务队列**:TBB中的任务队列负责存储待执行的任务,并在适当的时候将它们分派给空闲的线程。这种机制使得任务调度变得动态且高效,避免了线程间的过度同步和通信开销。 3. **并行算法**:TBB提供了一系列并行...

    进程和线程有什么区别?

    但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的...

    java 线程安全 是程序执行流的最小单元

    线程(thread),有时被称为轻量级进程...一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。

    线程调度模拟电梯

    一个进程可以包含多个线程,它们共享同一内存空间,可以并发执行,提高了系统资源的利用率。 2. **电梯模型**: 电梯问题常用于线程调度的示例,因为它涉及到多个任务(电梯)需要服务多个请求(楼层)。电梯的...

    C#多线程教程

    一个进程可以包含多个线程,这些线程共享进程的资源(如内存),但拥有独立的寄存器(栈指针、程序计数器等)。不同线程可以执行相同的函数或不同的函数。 - **什么是多线程?** - 多线程是指程序中包含多个执行流...

    android多线程模型和service分析

    2. **实现并发执行**:允许多个任务同时执行,提高程序效率。比如,一个线程负责网络数据加载,另一个线程处理图像渲染,主线程则负责UI更新,这样可以充分利用系统资源。 3. **优化多核处理器利用**:现代设备普遍...

    DSPBIOS多线程入门级要点

    DSPBIOS多线程技术是DSP系统中的一种高级编程技术,能够满足多个非相关的程序或函数同时运行的需求。这些程序运行和执行时间都有严格的要求,这些程序被称为线程(thread)。在DSP中任何独立执行的指令流都被称为...

    多线程,数据库优化,锁.docx

    多线程是计算机编程中的一个重要概念,指的是程序在执行过程中可以同时运行多个线程的能力。线程是程序执行流的基本单元,也是系统调度和分派的基本单位。在多线程环境下,每个线程都是一个独立的控制流,它们共享同...

Global site tag (gtag.js) - Google Analytics