在spring任务调度的基础上增加多线程
三种方式:
(1)使用OpenSymphony Quartz 调度器
(2)使用JDK Timer支持类
(3)SpringTaskExecutor抽象
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>
java后台调用
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(); } } } }}
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); }}
注意:
遇到的一个问题处理,即PC机作为服务器使用,可能长时间不关机,隔天之后会报如下错误:
Caused by: com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception:
原因:Mysql服务器默认的“wait_timeout”是8小时【也就是默认的值默认是28800秒】,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection,通俗的讲就是一个连接在8小时内没有活动,就会自动断开该连接