需求:作一個定時掃描的任務,每隔一段時間去掃描某個路徑下的xml文件。
分析:項目啓動時,就應該啓動定時掃描任務,在這裏用到了spring的定時器。
我這裏採起繼承QuartzJobBean的方式,任務類以下
#1.XmlScanImportTask.javajava
package com.scan; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * Created by Administrator on 2017/3/9 0009. */ public class XmlScanImportTask extends QuartzJobBean{ private boolean runningFlag=false; @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { //指定須要執行的任務 System.out.println("-------系統-------->當前時間:"+ new Date()); if(runningFlag){ LogUtil.info("掃描xml任務正在執行中..."); return; } runningFlag = true; try { //這裏實現本身的業務 }catch (Exception e){ e.printStackTrace(); LogUtil.error("掃描入庫出現異常"); }finally { runningFlag = false; LogUtil.info("掃描任務執行完畢"); } } }
#2.xml配置以下
scan.xmlspring
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"> <!-- 任務bean--> <bean id="jobDetailFactoryBean" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.scan.XmlScanImportTask"/> </bean> <!-- 觸發bean,設置任務的調度策略--> <bean id="cronTriggerFactoryBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="jobDetailFactoryBean"/> <!-- 每一個60秒觸發 --> <property name="cronExpression" value="0/60 * * * * ?"/> </bean> <!-- 調度工廠bean,激活觸發器,啓動quartz任務--> <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTriggerFactoryBean"/> </list> </property> </bean> </beans>
#3.線程池管理工具類以下數組
package com.scan; import com.zving.framework.utility.LogUtil; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * Created by Administrator on 2017/3/10 0010. */ public class ThreadPoolManager { //消息任務ID private static long _next_task_id = 0; //默認初始化線程數 public static final int DEFAULT_THREAD_NUM = 20; //默認最大併發線程數 public static final int MAX_THREAD_NUM = 20; //當前使用最大併發線程數 public int _cur_thread_num = 0; //線程池狀態 public boolean _is_closed = true; //線程任務列表 public List<ThreadTask> taskQueue = Collections.synchronizedList(new LinkedList<ThreadTask>()); //線程數組集合 public WorkThread[] threads; //線程對象 private static ThreadPoolManager _instance = null; //默認構造 private ThreadPoolManager(){ _cur_thread_num = DEFAULT_THREAD_NUM; threads = new WorkThread[_cur_thread_num]; for(int i = 0; i < _cur_thread_num; ++ i){ threads[i] = new WorkThread(i); } } //自定義線程數構造 public ThreadPoolManager(int thread_num){ _cur_thread_num = thread_num; threads = new WorkThread[_cur_thread_num]; for(int i = 0; i < _cur_thread_num; ++ i){ threads[i] = new WorkThread(i); } } /* singleton */ public static ThreadPoolManager getInstance(){ if(_instance == null){ synchronized(ThreadPoolManager.class){ if(_instance == null){ _instance = new ThreadPoolManager(); } } } return _instance; } public static synchronized long generateTaskId(){ // _next_task_id += (_next_task_id + 1) / 1000000; // if(_next_task_id == 0) _next_task_id ++; return _next_task_id++; } //開啓執行 public synchronized void start(){ if(!_is_closed){ LogUtil.info("線程池已經被初始化過..."); return ; } _is_closed = false; // LogUtil.info(String.format("ThreadPool Initializing----")); for(int i = 0; i < _cur_thread_num; ++ i){ threads[i].start(); // LogUtil.info(String.format("thread [%d] start!", i)); } //LogUtil.info(String.format("ThreadPool Initialized----,init "+_cur_thread_num+" thread")); } //關閉 public void close(){ if(!_is_closed){ waitforfinish(); _is_closed = true; taskQueue.clear(); } LogUtil.info("Thread pool close!"); } public void waitforfinish(){ synchronized(this){ _is_closed = true; notifyAll(); } for(int i = 0; i < _cur_thread_num; ++ i){ threads[i].stopThread(); LogUtil.info(String.format("Thread [%d] stop!", i)); } } //增長新任務 public void addTask(ThreadTask new_task){ synchronized(taskQueue){ if(_is_closed){ start(); } if(new_task != null){ taskQueue.add(new_task); taskQueue.notifyAll(); //taskQueue.notify(); } } } public int getTaskCount(){ return taskQueue.size(); } private class WorkThread extends Thread{ private int _index; private boolean _is_running = true; public WorkThread(int index){ _index = index; } public void run(){ while(_is_running){ ThreadTask t = getTask(); if(t != null){ t.run(); // System.out.println(_index); }else{ // 結束線程 LogUtil.info(String.format("thread [%d] exit", _index)); return; } } } public ThreadTask getTask(){ if(_is_closed) return null; ThreadTask r = null; synchronized (taskQueue) { while (taskQueue.isEmpty()) { try { /* 任務隊列爲空,則等待有新任務加入從而被喚醒 */ taskQueue.wait(); } catch (InterruptedException e) { LogUtil.error(e.getStackTrace()); } } /* 取出任務執行 */ r = (ThreadTask) taskQueue.remove(0); return r; } } public void stopThread(){ _is_running = false; try{ join(); }catch(InterruptedException ex){ LogUtil.error(ex.getStackTrace()); } } } }
#3.任務線程以下spring-mvc
package com.scan; /** * Created by Administrator on 2017/3/10 0010. */ public abstract class ThreadTask implements Runnable{ public long taskId = 0; public ThreadTask() { } public ThreadTask(long taskId) { this.taskId = taskId; } public long getTaskId() { return taskId; } public void setTaskId(long taskId) { this.taskId = ThreadPoolManager.generateTaskId(); } }
#4.實際業務任務線程以下
XmlScanImportThread.java併發
public class XmlScanImportThread extends ThreadTask{ String abfilePathTmp; Long siteIdTmp; public XmlScanImportThread(String abfilePathTmp, Long siteIdTmp) { this.abfilePathTmp = abfilePathTmp; this.siteIdTmp = siteIdTmp; } @Override public void run() { try { //實際業務 }catch (Exception e){ LogUtil.info("["+abfilePathTmp+"]解析失敗"); } } }