一个与业务无关的java多线程实现方法

来源:互联网 发布:民王 知乎 编辑:程序博客网 时间:2024/05/16 01:50
 


    前不久项目中做到接口同步数据,由于数据量比较大,所以考虑到了多线程,根据java设计思想,尽量解开耦合和模块化,所以这次设计出来一个线程组,将线程和业务分离,这正符合java设计思想中的松耦合。今天给大家分享一下。

这套多线程代码中一共有3个类构成,分别是以下三个

task.java 该类为一个抽象类,定义了一个方法,该类没有具体业务逻辑,作为一个多线程的抽象父类,待其他具体业务实现去继承,因为我多线程中要执行某个类的某个方法,肯定不能凭空去执行,所以搞一个父类,这样不管你执行什么任务,只要你继承我的这个task,业务实现写在我要执行的这个execut这个方法中,这样就实现了多线程和业务的无关性。

WorkThread 该类是继承于java的多线程Thread类,他主要负责将任务list类进行循环启动执行,这样就可以实现一个多线程类可以执行多个任务,该类中包含一个成员变量就是task的集合,当该类的run方法执行时就会将它本身的list 中的task任务循环进行执行。

 

TaskHandOut  该类是这个组合中的业务逻辑处理部分,它负责将线程平均分派,将任务平均分派到各个线程中。

具体见以下代码

1 task.java

import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * @author Thinkpad *  *         上午10:52:04 */public abstract class Task {public static final Log logger = LogFactory.getLog(Task.class);/** * 实现需要执行的任务 */public abstract void execute() throws Exception;public void execute_t() throws Exception {long starttime = System.currentTimeMillis();execute();long endtime = System.currentTimeMillis();long time = endtime - starttime;logger.info("执行单个任务消耗时间为:" + time + "ms.");}}


2WorkThread

import java.util.List;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * @author Thinkpad *  *         上午10:53:20 */public class WorkThread extends Thread {public static final Log logger = LogFactory.getLog(WorkThread.class);// 本线程待执行的任务列表private List<Task> taskList = null;/** * 构造工作线程,为其指派任务列表 *  * @param taskList *            执行的任务列表 */public WorkThread(List<Task> taskList) {this.taskList = taskList;}/** * 执行被指派的所有任务 */public void run() {logger.info("线程开始执行......");long starttime = System.currentTimeMillis();for (Task task : taskList) {try {task.execute_t();} catch (Exception e) {logger.error("执行任务出错!",e);}}long endtime = System.currentTimeMillis();long time = endtime - starttime;logger.info("当前线程" + this.currentThread().getId() +"执行消耗时间为:" + time + "ms.");}}


3TaskHandOut

 

public class TaskHandOut {public static final Log logger = LogFactory.getLog(TaskHandOut.class);//工作线程数private int threadCount;public TaskHandOut() {//默认启动线程数为5this.threadCount = 10;}/** * 指定启动线程数 * @param threadCount  1<theadCount<20 */public TaskHandOut(int tCount) throws Exception{if(tCount <1 || tCount >20)throw new Exception("启动线程数设置不合法![1-20]之间");this.threadCount = tCount;}/** * 将任务列表分发到工作线程中执行 * @param taskList  任务列表 */@SuppressWarnings("unchecked")public void threadLaunch(List<Task> taskList) {List[] taskListPerThread = handOutTasks(taskList, this.threadCount);System.out.println("实际要启动的工作线程数:" + taskListPerThread.length);logger.debug("实际启动的线程数:" + taskListPerThread.length);for (int i = 0; i < taskListPerThread.length; i++) {Thread workThread = new WorkThread(taskListPerThread[i]);workThread.start();}}/** * 把 List 中的任务分配给每个线程 *  * @param taskList *            待分派的任务列表 * @param threadCount *            线程数 * @return  */@SuppressWarnings("unchecked")private static List[] handOutTasks(List<Task> taskList, int threadCount) {logger.info("要执行的任务数为:" + taskList.size());// 每个线程至少要执行的任务数int minTaskCount = taskList.size() / threadCount;// 平均分配后还剩下的任务数int remainTaskCount = taskList.size() % threadCount;// 实际要启动的线程数int actualThreadCount = minTaskCount > 0 ? threadCount: remainTaskCount;List<Task>[] taskListPerThread = new List[actualThreadCount];int taskIndex = 0;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--;}}return taskListPerThread;}public static void main(String[] args) throws Exception {List<Task> taskList = new ArrayList();for (int i = 0; i < 100; i++) {taskList.add(new TaskItem());}TaskHandOut tt = new TaskHandOut(15);tt.threadLaunch(taskList);}}class TaskItem extends Task {/* (non-Javadoc) * @see com.p95169.hrs.thread.Task#execute() */@Overridepublic void execute() throws Exception {System.out.println("开始执行任务!");}}

具体使用如下

你需要将你的具体业务实现类继承于task类,并将具体方法写入到exeute方法中,或者你多写一个类,将你的业务类注入进来,在另外你单独写的类上exeute调用你的业务方法。这样要看你具体需求。以下贴出来我自己的用法

List<Task> taskLst=new ArrayList<Task>();

ApplicationContext ctx =SpringContextHolder.getApplicationContext();
   for (int i = 0; i < li.size();i++) {
    HospitalVO hi = li.get(i);
    deptMgrSynThread=(DeptSynThread) ctx.getBean("bjDeptMgrSynThread");
    deptMgrSynThread.setHi(hi);
    taskLst.add(deptMgrSynThread);
    }
   taskHandOut.threadLaunch(taskLst);

deptMgrSynThread就是我单独写的实现task的实现类,为了将我的业务类注入进来。

以上对象taskHandOut 的获得我是靠spring注入的,当然大家也可以直接new获得,根据你具体应用而变。