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

年底总结2-spring多线程任务调度

 
阅读更多

 1、spring framework开发参考手册中第23掌"spring中的定时调度(Scheduling)和线程池(Thread Pooling)"提到三种方式:

(1)使用OpenSymphony Quartz 调度器

(2)使用JDK Timer支持类

(3)SpringTaskExecutor抽象

 

2、实际业务需求说明

(1)同时向50台设备采集数据,并保存本地数据库。

(2)每30秒钟执行一次调度,完成对这50台设备数据的读取。

 

3、根据实际业务分析,属于多线程并发处理任务,于是采用SpringTaskExecutor抽象方式完成

 

4、spring 容器配置

 

<!-- 接收数据 -->
    <!-- 异步线程池 -->
    <bean id="threadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <!-- 核心线程数  -->
    <property name="corePoolSize" value="10" />
    <!-- 最大线程数 -->
    <property name="maxPoolSize" value="100" />
    <!-- 队列最大长度 >=mainExecutor.maxSize -->
    <property name="queueCapacity" value="1000" />
    <!-- 线程池维护线程所允许的空闲时间 -->
    <property name="keepAliveSeconds" value="300" />
    <!-- 线程池对拒绝任务(无线程可用)的处理策略 -->
    <property name="rejectedExecutionHandler">
    	<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
    </property>
    </bean>
    
    <bean id="collectSalesOrderExecutor" class="com.fts.internal.CollectSalesOrderExecutor">
    	<property name="threadPool" ref="threadPool" />
    	<property name="dataSource" ref="dataSource" />
    </bean>
    
    <bean id="springScheduleExecutorTask" class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
    	<property name="runnable" ref="collectSalesOrderExecutor" />
    	<!-- 容器加载10秒后开始执行 -->
    	<property name="delay" value="10000" />
    	<!-- 每次任务间隔 30秒-->
    	<property name="period" value="30000" />
    	
    </bean>
    
    <bean id="springScheduledExecutorFactoryBean" class="org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean">
    	<property name="scheduledExecutorTasks" >
    	<list>
    		<ref bean="springScheduleExecutorTask" />
    	</list>
    	</property>
    </bean>

 

 

5、java调用

(1) collectSalesOrderExecutor.java

 

public class CollectSalesOrderExecutor extends TimerTask {

	//注入ThreadPoolTaskExecutor 到主线程中
	private ThreadPoolTaskExecutor threadPool;
	private JdbcTemplate template;
	
	public void setThreadPool(ThreadPoolTaskExecutor threadPool) {
		this.threadPool = threadPool;
	}
	
	//注入数据源
	public void setDataSource(DataSource dataSource) {
		this.template = new JdbcTemplate(dataSource);
	}

	@Override
	public void run() {
		System.out.format("开始执行 %s ...%n", new Date());
		@SuppressWarnings("unchecked")
		//取得设备列表
		List<Equipment> ipList = template.query("select e.* from equipment e ", ParameterizedBeanPropertyRowMapper.newInstance(Equipment.class));
		if (ipList != null) {
			for (Equipment equipment : ipList) {
				try {
					//执行向各个设备采集数据并保存数据库
					threadPool.execute(new CollectSalesOrderTask(template,equipment.getIp()));
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		}

	}

}

 

(2)CollectSalesOrderTask.java

public class CollectSalesOrderTask implements Runnable {
	private String ip;
	private JdbcTemplate template;

	public CollectSalesOrderTask(JdbcTemplate template, String ip) {
		this.template = template;
		this.ip = ip;
	}

	@Override
	public void run() {
		// 连接设备
		System.out.format("执行采集数据 %s ...%n", ip);
		//接收设备数据
		List<Report> list = JhscaleCommunicationUtils.getDeviceSales(this.ip);
		//保存本地数据库
		if (list != null && !list.isEmpty())
			storeSalesOrder(list);
	}
}

 

 

 

6、遇到的一个问题处理,即PC机作为服务器使用,可能长时间不关机,隔天之后会报如下错误:

Caused by: com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: 

 

原因:Mysql服务器默认的“wait_timeout”是8小时【也就是默认的值默认是28800秒】,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection,通俗的讲就是一个连接在8小时内没有活动,就会自动断开该连接。

 

解决:如下

D:\MySQL\MySQL Server 5.1\my.ini
[mysqld]

# The TCP/IP Port the MySQL Server will listen on
port=3306

---------位置下面添加-----------
# this is myown dinifition for mysql connection timeout
wait_timeout=31536000
interactive_timeout=31536000

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics