1. 程式人生 > >Spring事務內多執行緒處理-解決方案

Spring事務內多執行緒處理-解決方案

首先,Spring Ioc 依賴注入的就是單例物件,我們在使用的時候如果有多個相同處理且不怎麼耗時的情況下一般會採用for迴圈直接執行,這樣的情況下即使有事務管理也不會影響業務執行下去;但是,大多數的應用比如:系統與系統之間的互動就比較耗時了,此時使用for迴圈執行業務就不可取了,於是我們想用執行緒來解決這個問題。這裡面踩過的坑只有自己爬出來才知道里面箇中緣由。

======================本篇多執行緒處理是依靠資料來源配置解決的==================

另外,附帶說明一下:如果是在Spring提供的@Test下測試:如果有多執行緒處理,需要呼叫Thread.sleep(3000);

實現執行緒等待,這也是測試多執行緒模式下所必須的。如果不加執行緒休眠,不等待多執行緒執行完畢,很有可能測不出來多執行緒呼叫的處理。

前提:呼叫業務方法中實現多執行緒執行多個相同操作。

問題:如果是在Spring 事務管理下的方法內採用多執行緒處理任務是否可行呢?

一般情況下,我們只需要在呼叫的時候@autowire 我們需要的service類即可。理想狀態下,以下程式碼是最常見的實現:

1.建立一個業務執行緒類

package com.wlyd.fmcgwms.util.thread;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import com.wlyd.fmcgwms.persistence.beans.platform.Corporation;
import com.wlyd.fmcgwms.service.basic.WmStockService;

public class UpdateProductThead extends Thread {
    
     private ThreadPoolTaskExecutor taskExecutor;
     
     public ThreadPoolTaskExecutor getTaskExecutor() {
         return taskExecutor;
     }
     
     public void setTaskExecutor(ThreadPoolTaskExecutor taskExecutor) {
         this.taskExecutor = taskExecutor;
     }
    
    ExecutorService executorService; 
    
    private WmStockService wmStockService;
    
    private List<Corporation> corporations;
    
    public UpdateProductThead( WmStockService wmStockService,List<Corporation> corporations) {
        this.wmStockService = wmStockService;
        this.corporations = corporations;
        executorService = Executors.newFixedThreadPool(corporations==null?0:corporations.size()); 
    }

    /*@Override
    public void run() {
        for (int i = 0; i < corporations.size(); i++) {
            new Thread(new DoBusinessThread(i));
        }
    }*/
    
    @Override
    public void run() {
        taskExecutor=new ThreadPoolTaskExecutor();
        for (int i = 0; i < corporations.size(); i++) {
            taskExecutor.execute(new DoBusinessThread(i));
        }
    }
    
    /*@Override
    public void run() {
        for (int i = 0; i < corporations.size(); i++) {
            executorService.execute(new DoBusinessThread(i));
            System.out.println();
        }
    }*/

    class DoBusinessThread extends Thread{
        
        private int index=0;
        
        public DoBusinessThread(int index){
            this.index=index;
        }

        @Override
        public void run() {
            wmStockService.updateProductStockProcess(corporations.get(index)); 
        }
        
    }

}

以上三種方式的執行緒run執行效果都是一樣的。

2.測試業務執行緒類執行情況

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class APIServiceTest {

       @Autowired
    WmStockService wmStockService;
    
    @Autowired
    CorporationMapper corporationMapper;
        
	@Test
	public void testUpdateProductWithThread(){
		List<Corporation> corporations=corporationMapper.findAll();
		
		new UpdateProductThead(wmStockService, corporations);
	}
}
我們最願意看到的情況是程式執行下去就成功了,但是這卻是事與願違的。按照上面的寫法沒有一個業務執行緒會執行。

當我們的執行緒內run方法只執行如下方法時:

wmStockService.updateProductStockProcess(corporation);
我們能執行成功有且僅有一個執行緒成功,然後資料來源就關閉了。
package com.wlyd.fmcgwms.util.thread;

import com.wlyd.fmcgwms.persistence.beans.platform.Corporation;
import com.wlyd.fmcgwms.service.basic.WmStockService;

public class UpdateProductThead extends Thread {
	
	private WmStockService wmStockService;
	
	private Corporation corporations;
	
	public UpdateProductThead( WmStockService wmStockService,Corporation corporation) {
		this.wmStockService = wmStockService;
		this.corporation = corporation; 
	}

	@Override
	public void run() {
           wmStockService.updateProductStockProcess(corporation);
       }
}

3.最原始的For迴圈

外部業務呼叫:

public void updateProductStock() {
		try {
			List<Corporation> corps = corporationMapper.findAll();
			if (corps == null || corps.size() == 0) {
				return ;
			}
			for (Corporation corporation : corps) {
				// 排除系統組織賬號
				if (corporation.getEsCorAlias() == null
						|| corporation.getEsCorAlias().equals("")
						|| corporation.getEsCorAlias().equals("10000")
						|| corporation.getEsCorAlias().equals("10002")) {
					continue;
				}
				wmStockService.updateProductStockProcess(corporation);
				// 開啟執行緒處理商品庫存同步---Spring管理的物件都是單例模式的,所以for批量處理的方式是不行的
				//new UpdateProductThead(wmStockService, corporation).start();
			}
		} catch (Exception e) {
			Log.getLogger(getClass()).error(">>>>呼叫九州通達OMS庫存同步介面呼叫異常:"+e.getMessage());
		}

}
業務處理方法(詳細的過程就不貼上來了):
public void updateProductStockProcess(Corporation corporation) {

      // 遠端介面訪問

      // 本地儲存介面呼叫日誌
}
測試:
@Test
public void testUpdateProduct(){
	quartzJobService.updateProductStock();
}

這次卻可以正常的執行:

2016-07-29 16:53:46,553 [main] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-07-29 16:53:46,553 [main] DEBUG [java.sql.Connection] - ==>  Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10003 st LEFT JOIN cd_wh_itme_10003 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-07-29 16:53:46,553 [main] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-07-29 16:53:46,617 [main] INFO  [com.wlyd.fmcgwms.service.platform.impl.JZTDAPIServiceImpl] - 呼叫九州通達OMS介面.........../updateproductstock REQUEST:{"Products":[{"AvailableProductNum":20,"ProductCode":"10003160503009","ProductNum":40,"ProductUnit":"斤"},{"AvailableProductNum":100,"ProductCode":"10003160503009","ProductNum":100,"ProductUnit":"條"},{"AvailableProductNum":13,"ProductCode":"10003160503001","ProductNum":14,"ProductUnit":"只"},{"AvailableProductNum":7,"ProductCode":"10003160503002","ProductNum":10,"ProductUnit":"只"},{"AvailableProductNum":50,"ProductCode":"10003160503002","ProductNum":100,"ProductUnit":"斤"},{"AvailableProductNum":40,"ProductCode":"10003160503005","ProductNum":100,"ProductUnit":"斤"},{"AvailableProductNum":0,"ProductCode":"10003160503005","ProductNum":5,"ProductUnit":"箱"},{"AvailableProductNum":0,"ProductCode":"10003160503007","ProductNum":30,"ProductUnit":"斤"},{"AvailableProductNum":20,"ProductCode":"10003160503007","ProductNum":25,"ProductUnit":"箱"},{"AvailableProductNum":5,"ProductCode":"10003160503004","ProductNum":55,"ProductUnit":"箱"},{"AvailableProductNum":50,"ProductCode":"10003160503006","ProductNum":149,"ProductUnit":"斤"},{"AvailableProductNum":0,"ProductCode":"10003160503006","ProductNum":6,"ProductUnit":"箱"},{"AvailableProductNum":0,"ProductCode":"10003160503003","ProductNum":100,"ProductUnit":"斤"},{"AvailableProductNum":7,"ProductCode":"10003160503008","ProductNum":7,"ProductUnit":"斤"},{"AvailableProductNum":9,"ProductCode":"10003160503008","ProductNum":9,"ProductUnit":"箱"}]}
2016-07-29 16:53:46,618 [main] INFO  [com.wlyd.fmcgwms.service.platform.impl.JZTDAPIServiceImpl] - 呼叫九州通達OMS介面.........../updateproductstock NO RESPONSE:Illegal character(s) in message header value: *
2016-07-29 16:53:46,622 [main] ERROR [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>呼叫九州通達OMS庫存同步介面日誌儲存:true
2016-07-29 16:53:46,624 [main] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-07-29 16:53:46,624 [main] DEBUG [java.sql.Connection] - ==>  Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10004 st LEFT JOIN cd_wh_itme_10004 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-07-29 16:53:46,624 [main] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-07-29 16:53:46,629 [main] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10004)測試新增組織沒有庫存記錄!!!
2016-07-29 16:53:46,630 [main] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-07-29 16:53:46,630 [main] DEBUG [java.sql.Connection] - ==>  Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10005 st LEFT JOIN cd_wh_itme_10005 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-07-29 16:53:46,630 [main] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-07-29 16:53:46,633 [main] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10005)新增組織測試預警資訊選單沒有庫存記錄!!!
2016-07-29 16:53:46,633 [main] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-07-29 16:53:46,633 [main] DEBUG [java.sql.Connection] - ==>  Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10006 st LEFT JOIN cd_wh_itme_10006 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-07-29 16:53:46,633 [main] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-07-29 16:53:46,636 [main] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10006)test1沒有庫存記錄!!!
2016-07-29 16:53:46,637 [main] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-07-29 16:53:46,637 [main] DEBUG [java.sql.Connection] - ==>  Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10007 st LEFT JOIN cd_wh_itme_10007 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-07-29 16:53:46,637 [main] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-07-29 16:53:46,640 [main] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10007)aaabbbbbb沒有庫存記錄!!!
2016-07-29 16:53:46,640 [main] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-07-29 16:53:46,640 [main] DEBUG [java.sql.Connection] - ==>  Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10008 st LEFT JOIN cd_wh_itme_10008 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-07-29 16:53:46,641 [main] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-07-29 16:53:46,643 [main] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10008)測試新增專用組織沒有庫存記錄!!!
按序列執行下去就可以,但這不是我們需要的方式,我們需要執行緒來解決這種資料量大且耗時的操作。

注:這裡通過排程任務來開啟多執行緒處理,不是Action/Controller發起的請求。

4.配置Spring管理執行緒池

 <!-- 配置執行緒池 -->  
    <bean id ="taskExecutor"  class ="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >  
        <!-- 執行緒池維護執行緒的最少數量 -->  
   		<property name ="corePoolSize" value ="5" />  
        <!-- 執行緒池維護執行緒所允許的空閒時間 -->  
   		<property name ="keepAliveSeconds" value ="30000" />  
        <!-- 執行緒池維護執行緒的最大數量 -->  
    	<property name ="maxPoolSize" value ="1000" />  
        <!-- 執行緒池所使用的緩衝佇列 -->  
    	<property name ="queueCapacity" value ="200" />  
    </bean>  

修改業務執行緒:
package com.wlyd.fmcgwms.util.thread;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import com.wlyd.fmcgwms.persistence.beans.platform.Corporation;
import com.wlyd.fmcgwms.service.basic.WmStockService;
/**
 * 多執行緒業務處理類
 * 
 * @packge com.wlyd.fmcgwms.util.thread.UpdateProductThead
 * @date   2016年7月29日  下午5:56:22
 * @author pengjunlin
 * @comment   
 * @update
 */
public class UpdateProductThead extends Thread {
	
	public static final int THREAD_COMMON=0;
	
	public static final int THREAD_EXCUTOR_SERVICE=1;
	
	public static final int THREAD_POOL_TASK_EXCUTOER=2;
	
	private ThreadPoolTaskExecutor taskExecutor;
	
	private ExecutorService executorService; 
	
	private WmStockService wmStockService;
	
	private List<Corporation> corporations;
	
	private int threadType;
	
	public UpdateProductThead(int threadType,ThreadPoolTaskExecutor taskExecutor,WmStockService wmStockService,List<Corporation> corporations) {
		this.wmStockService = wmStockService;
		this.corporations = corporations;
		this.executorService = Executors.newFixedThreadPool(corporations==null?0:corporations.size()); 
		this.threadType=threadType;
	}

	@Override
	public void run() {
		for (int i = 0; i < corporations.size(); i++) {
			switch (threadType) {
			case 0:
				// 方式一
				new Thread(new DoBusinessThread(i));
				break;
			case 1:
				// 方式二
				taskExecutor.execute(new DoBusinessThread(i));
				break;
			case 2:
				// 方式三
				executorService.execute(new DoBusinessThread(i));
				break;
			default:
				break;
			}
			
		}
	}
	

	class DoBusinessThread extends Thread{
		
		private int index=0;
		
		public DoBusinessThread(int index){
			this.index=index;
		}

		@Override
		public void run() {
			wmStockService.updateProductStockProcess(corporations.get(index)); 
		}
		
	}

}
修改測試:
@Test
public void testUpdateProductWithThread(){
	List<Corporation> corporations=corporationMapper.findAll();
		
	new UpdateProductThead(UpdateProductThead.THREAD_POOL_TASK_EXCUTOER,taskExecutor,wmStockService, corporations);
}

執行測試 還是沒有執行,spring輸出日誌:

2016-08-01 09:28:07,422 [Thread-4] INFO  [org.springframework.context.support.GenericApplicationContext] - Closing [email protected]c7a4e4: startup date [Mon Aug 01 09:28:03 CST 2016]; root of context hierarchy
2016-08-01 09:28:07,426 [Thread-4] INFO  [org.springframework.context.support.DefaultLifecycleProcessor] - Stopping beans in phase 2147483647
2016-08-01 09:28:07,427 [Thread-4] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED paused.
2016-08-01 09:28:07,427 [Thread-4] INFO  [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Destroying singletons in org.s[email protected]4e08711f: defining beans [wmStockAlertRlueServiceImpl,wmWarringInfoServiceImpl,cdWarehouseServiceImpl,cdWhCustomerServiceImpl,cdWhItmeServiceImpl,cdWhLocAreaServiceImpl,cdWhLocationServiceImpl,wmStockAdjustServiceImpl,wmStockFreezeServiceImpl,wmStockReleaseServiceImpl,wmStockServiceImpl,esMenuFunctionsServiceImpl,esMrRightsServiceImpl,esMuRightsServiceImpl,WMWareHouseStatServiceImpl,esDictionaryServiceImpl,esDictionaryTypeServiceImpl,esExceptionServiceImpl,esIconsServiceImpl,esMenuServiceImpl,esPropertiesServiceImpl,esRoleServiceImpl,esUserServiceImpl,wmIntoOrderBatchCodenoServiceImpl,wmIntoOrderinfoServiceImpl,wmIntoOrderServiceImpl,wmReceiptServiceImpl,wmReturnInfoServiceImpl,wmInventorySheetDetailServiceImpl,wmInventorySheetServiceImpl,wmWarehouseMoveServiceImpl,ebInterfaceLogServiceImpl,ebIntoStockLogServiceImpl,ebOperateLogServiceImpl,ebOutStockLogServiceImpl,ebSysLogServiceImpl,wmBatchPickingServiceImpl,wmOutOrderDetailServiceImpl,wmOutOrderServiceImpl,APIForOMSServiceImpl,APIServiceImpl,corporationServiceImpl,esSaasServiceInfoServiceImpl,JZTDAPIServiceImpl,padServiceImpl,pdaApiImpl,quartzJobServiceImpl,statisticalChartsServiceImpl,stockWarringJobServiceImpl,syncOrderStutusServiceImpl,timerTaskServiceImpl,reportServiceImpl,wmItemDailyReportServiceImpl,cdWhUnpickServiceImpl,settingsServiceImpl,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,dataSource,sqlSessionFactory,sqlSession,org.mybatis.spring.mapper.MapperScannerConfigurer#0,transactionManager,txAdvice,org.springframework.aop.config.internalAutoProxyCreator,pc,org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0,InitSysProperties,DailyTaskJob,DailyTaskJobMethod,DailyTaskCronTriggerBean,DailyTaskJobMethodSaas,DailyTaskCronTriggerBeanSaas,StockWarringTaskJob,StockWarringTaskJobMethod,StockWarringTaskCronTriggerBean,CycleSendInterfaceInfoTaskJob,CycleSendInterfaceInfoTaskJobMethod,CycleSendInterfaceInfoTaskCronTriggerBean,SpringJobSchedulerFactoryBean,taskExecutor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,wmStockAlertRuleMapper,wmWarringInfoMapper,cdCustomerMapper,cdWarehouseMapper,cdWhItmeMapper,cdWhLocAreaMapper,cdWhLocationMapper,wmStockAdjustMapper,wmStockFreezeMapper,wmStockMapper,wmStockReleaseMapper,esMenuFunctionsMapper,esMrRightsMapper,esMuRightsMapper,esDictionaryMapper,esDictionaryTypeMapper,ebUserWarehouseMapper,esExceptionMapper,esIconsMapper,esMenuMapper,esPropertiesMapper,esRoleMapper,esUserMapper,wmIntoOrderBatchCodenoMapper,wmIntoOrderCodenoMapper,wmIntoOrderInfoMapper,wmIntoOrderMapper,wmReceiptInfoMapper,wmReturnInfoMapper,wmInventorySheetDetailMapper,wmInventorySheetMapper,wmWarehouseMoveCodenoMapper,wmWarehouseMoveMapper,ebInterfaceLogMapper,ebIntoStockLogMapper,ebOperateLogMapper,ebOutStockLogMapper,ebSysLogMapper,wmAssignedPickcarMapper,wmBatchPickingMapper,wmOutOrderCodenoMapper,wmOutOrderDetailMapper,wmOutOrderMapper,wmStockAssignedMapper,corporationMapper,esSaasServiceInfoMapper,statisticalChartsMapper,wmItemTransferMapper,reportMapper,wmDailyItemReportMapper,settingsMapper,wmUnpickMapper]; root of factory hierarchy
2016-08-01 09:28:07,451 [Thread-4] INFO  [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] 
            - Shutting down ExecutorService 'taskExecutor'
2016-08-01 09:28:07,452 [Thread-4] INFO  [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Shutting down Quartz Scheduler
2016-08-01 09:28:07,452 [Thread-4] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED shutting down.
2016-08-01 09:28:07,452 [Thread-4] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED paused.
2016-08-01 09:28:07,459 [Thread-4] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED shutdown complete.
2016-08-01 09:28:07,482 [Thread-4] INFO  [com.alibaba.druid.pool.DruidDataSource] - {dataSource-1} closed

從日誌看,應該是spring不支援多執行緒處理,該執行緒一啟動就被關閉了。錯了,並不是spring不支援多執行緒,那是因為我忘了寫執行緒的呼叫start(),於是才寫了下面的第5點;

new UpdateProductThead(UpdateProductThead.THREAD_POOL_TASK_EXCUTOER,taskExecutor,wmStockService, corporations).start();
重新執行,控制檯輸出:
2016-08-01 13:52:46,518 [Thread-4] INFO  [com.alibaba.druid.pool.DruidDataSource] - {dataSource-1} closed
Exception in thread "pool-1-thread-8" Exception in thread "pool-1-thread-2" org.springframework.transaction.CannotCreateTransactionException: 
Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.DataSourceDisableException
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:241)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at com.sun.proxy.$Proxy81.updateProductStockProcess(Unknown Source)
	at com.wlyd.fmcgwms.util.UpdateProductThread$DoBusinessThread.run(UpdateProductThread.java:71)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: com.alibaba.druid.pool.DataSourceDisableException
	at com.alibaba.druid.pool.DruidDataSource.pollLast(DruidDataSource.java:1399)
	at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1021)
	at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:898)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:882)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:872)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:97)
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:203)
資料來源提前關閉了,這裡初步可以看出是資料庫連線池的問題。接下來進一步測試(因為此前沒有呼叫start()所以沒看出真實的問題所在)。

5.Spring注入執行緒類處理

再次嘗試使用@service掃描實現執行緒處理:

<pre name="code" class="java">package com.wlyd.fmcgwms.service.thread;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import com.wlyd.fmcgwms.persistence.beans.Settings;
import com.wlyd.fmcgwms.persistence.beans.platform.Corporation;
import com.wlyd.fmcgwms.persistence.mapper.SettingsMapper;
import com.wlyd.fmcgwms.service.basic.WmStockService;
import com.wlyd.fmcgwms.util.base.BaseServiceImpl;
/**
 * 多執行緒業務處理類
 * 
 * @packge com.wlyd.fmcgwms.util.thread.UpdateProductThead
 * @date   2016年7月29日  下午5:56:22
 * @author pengjunlin
 * @comment   
 * @update
 */
@Service
public class UpdateProductThead  extends BaseServiceImpl<Settings, String> implements Runnable {
	
	public static final int THREAD_COMMON=0;
	
	public static final int THREAD_EXCUTOR_SERVICE=1;
	
	public static final int THREAD_POOL_TASK_EXCUTOER=2;
	
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;
	
	private ExecutorService executorService; 
	
	private WmStockService wmStockService;
	
	private List<Corporation> corporations;
	
	private int threadType;
	
	@Autowired
	private SettingsMapper settingsMapper;

	@PostConstruct
	public void init() {
		this.dao = settingsMapper;
	}
	
	public UpdateProductThead() {
		super();
	}

	public UpdateProductThead(int threadType,WmStockService wmStockService,List<Corporation> corporations) {
		this.wmStockService=wmStockService;
		this.corporations = corporations;
		this.executorService = Executors.newFixedThreadPool(corporations==null?0:corporations.size()); 
		this.threadType=threadType;
	}

	@Override
	public void run() {
		for (int i = 0; i < corporations.size(); i++) {
			switch (threadType) {
			case 0:
				// 方式一
				new Thread(new DoBusinessThread(wmStockService,i));
				break;
			case 1:
				// 方式二
				taskExecutor.execute(new DoBusinessThread(wmStockService,i));
				//new DoLogicThread(0).start();
				break;
			case 2:
				// 方式三
				executorService.execute(new DoBusinessThread(wmStockService,i));
				break;
			default:
				break;
			}
			
		}
	}
	

	class DoBusinessThread extends Thread{
		
		WmStockService wmStockService;
		
		private int index=0;
		
		public DoBusinessThread(WmStockService wmStockService,int index){
			this.wmStockService=wmStockService;
			this.index=index;
		}

		@Override
		public void run() {
			wmStockService.updateProductStockProcess(corporations.get(index)); 
		}
		
	}
	
	class DoLogicThread extends Thread{
		
		private int index=0;
		
		public DoLogicThread(int index){
			this.index=index;
		}

		@Override
		public void run() {
			System.out.println("Do logic counting:"+index);
		}
		
	}

}
執行測試方法:
@Autowired
CorporationMapper corporationMapper;
    
@Autowired
WmStockService wmStockService;

@Test
public void testUpdateProductthread(){
	List<Corporation> corporations=corporationMapper.findAll();
	new Thread(new UpdateProductThead(UpdateProductThead.THREAD_POOL_TASK_EXCUTOER,wmStockService, corporations)).start();
}

明確地給出了執行緒處理是資料來源設定的問題,控制檯輸出如下:
2016-08-01 13:57:11,892 [Thread-4] INFO  [com.alibaba.druid.pool.DruidDataSource] - {dataSource-1} closed
Exception in thread "pool-1-thread-2" org.springframework.transaction.CannotCreateTransactionException: 
Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.DataSourceDisableException
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:241)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at com.sun.proxy.$Proxy81.updateProductStockProcess(Unknown Source)
	at com.wlyd.fmcgwms.service.thread.UpdateProductThead$DoBusinessThread.run(UpdateProductThead.java:101)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: com.alibaba.druid.pool.DataSourceDisableException
	at com.alibaba.druid.pool.DruidDataSource.pollLast(DruidDataSource.java:1399)
	at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1021)
	at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:898)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:882)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:872)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:97)
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:203)
	... 13 more
Exception in thread "pool-1-thread-4" org.springframework.transaction.CannotCreateTransactionException:
 Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.DataSourceDisableException
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:241)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at com.sun.proxy.$Proxy81.updateProductStockProcess(Unknown Source)
	at com.wlyd.fmcgwms.service.thread.UpdateProductThead$DoBusinessThread.run(UpdateProductThead.java:101)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: com.alibaba.druid.pool.DataSourceDisableException
	at com.alibaba.druid.pool.DruidDataSource.pollLast(DruidDataSource.java:1399)
	at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1021)
	at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:898)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:882)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:872)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:97)
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:203)
	... 13 more
Exception in thread "pool-1-thread-8" org.springframework.transaction.CannotCreateTransactionException:
 Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.DataSourceDisableException
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:241)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at com.sun.proxy.$Proxy81.updateProductStockProcess(Unknown Source)
	at com.wlyd.fmcgwms.service.thread.UpdateProductThead$DoBusinessThread.run(UpdateProductThead.java:101)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: com.alibaba.druid.pool.DataSourceDisableException
	at com.alibaba.druid.pool.DruidDataSource.pollLast(DruidDataSource.java:1399)
	at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1021)
	at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:898)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:882)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:872)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:97)
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:203)
	... 13 more
Exception in thread "pool-1-thread-6" org.springframework.transaction.CannotCreateTransactionException:
 Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.DataSourceDisableException
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:241)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at com.sun.proxy.$Proxy81.updateProductStockProcess(Unknown Source)
	at com.wlyd.fmcgwms.service.thread.UpdateProductThead$DoBusinessThread.run(UpdateProductThead.java:101)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

好了終於找到問題,就是資料庫連線池多執行緒配置的問題。

6.配置資料庫連線池

 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"    destroy-method="close" >
    <property name="driverClassName">
      <value>${jdbc.driverClass}</value>
    </property>
    <property name="url">
      <value>${jdbc.jdbcUrl}</value>
    </property>
    <property name="username">
      <value>${jdbc.user}</value>
    </property>
    <property name="password">
      <value>${jdbc.password}</value>
    </property>
    <!-- 連線池最大使用連線數 -->
    <property name="maxActive">
      <value>20</value>
    </property>
    <!-- 初始化連線大小 -->
    <property name="initialSize">
      <value>10</value>
    </property>
    <!-- 獲取連線最大等待時間 -->
    <property name="maxWait">
      <value>60000</value>
    </property>
    <!-- 連線池最大空閒 -->
    <property name="maxIdle">
      <value>20</value>
    </property>
    <!-- 連線池最小空閒 -->
    <property name="minIdle">
      <value>3</value>
    </property>
    <!-- 自動清除無用連線 -->
    <property name="removeAbandoned">
      <value>true</value>
    </property>
    <!-- 清除無用連線的等待時間 -->
    <property name="removeAbandonedTimeout">
      <value>180</value>
    </property>
    <!-- 連線屬性 -->
    <property name="connectionProperties">
      <value>clientEncoding=UTF-8</value>
    </property>
  </bean>

將initialSize改成大於1的數字(因為是開發環境,預設配成的是1)。

配置完成後測試執行,整個問題總算是解決了,控制檯輸出如下:

2016-08-01 14:21:30,815 [main] INFO  [org.quartz.core.QuartzScheduler] -
 JobFactory set to: [email protected]3d
2016-08-01 14:21:30,824 [main] INFO  [org.springframework.context.support.DefaultLifecycleProcessor] - Starting beans in phase 2147483647
2016-08-01 14:21:30,824 [main] INFO  [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Starting Quartz Scheduler now
2016-08-01 14:21:30,824 [main] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED started.
2016-08-01 14:21:30,834 [main] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-08-01 14:21:30,834 [main] DEBUG [java.sql.Connection] - ==> 
 Preparing: select ES_COR_ID, ES_COR_NAME,ES_COR_ALIAS, ES_COR_ADDRESS, ES_COR_JURIDICAL_PERSON, ES_COR_CONTACT_EMAIL, 
ES_COR_CONTACT_TEL,ES_COR_DESCRIBE, ES_COR_NOTE,ES_COR_CREATE_TIME,ES_COR_MODIFY_TIME from es_corporation 
2016-08-01 14:21:30,834 [main] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-08-01 14:21:30,873 [pool-1-thread-2] DEBUG [java.sql.Connection] - ooo Using Connection [com.mysql.jdbc.[email protected]]
2016-08-01 14:21:30,873 [pool-1-thread-6] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-08-01 14:21:30,874 [pool-1-thread-2] DEBUG [java.sql.Connection] - ==> 
 Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,
st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10001 st 
LEFT JOIN cd_wh_itme_10001 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-08-01 14:21:30,874 [pool-1-thread-6] DEBUG [java.sql.Connection] - ==> 
 Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,
st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10005 st
 LEFT JOIN cd_wh_itme_10005 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-08-01 14:21:30,874 [pool-1-thread-6] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-08-01 14:21:30,874 [pool-1-thread-1] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-08-01 14:21:30,875 [pool-1-thread-1] DEBUG [java.sql.Connection] - ==>  
Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit
 FROM wm_stock_10000 st LEFT JOIN cd_wh_itme_10000 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-08-01 14:21:30,875 [pool-1-thread-1] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-08-01 14:21:30,874 [pool-1-thread-5] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-08-01 14:21:30,874 [pool-1-thread-2] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-08-01 14:21:30,875 [pool-1-thread-5] DEBUG [java.sql.Connection] - ==> 
 Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit
 FROM wm_stock_10004 st LEFT JOIN cd_wh_itme_10004 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-08-01 14:21:30,875 [pool-1-thread-5] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-08-01 14:21:30,876 [pool-1-thread-3] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-08-01 14:21:30,876 [pool-1-thread-3] DEBUG [java.sql.Connection] - ==>
 Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit
 FROM wm_stock_10002 st LEFT JOIN cd_wh_itme_10002 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-08-01 14:21:30,876 [pool-1-thread-3] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-08-01 14:21:30,878 [Thread-4] INFO  [org.springframework.context.support.GenericApplicationContext] 
- Closing [email protected]c7a4e4: startup date [Mon Aug 01 14:21:27 CST 2016]; root of context hierarchy
2016-08-01 14:21:30,879 [Thread-4] INFO  [org.springframework.context.support.DefaultLifecycleProcessor] 
- Stopping beans in phase 2147483647
2016-08-01 14:21:30,880 [Thread-4] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED paused.
2016-08-01 14:21:30,880 [Thread-4] INFO  [org.springframework.beans.factory.support.DefaultListableBeanFactory] 
- Destroying singletons in org.s[email protected]4e08711f: defining beans [wmStockAlertRlueServiceImpl,wmWarringInfoServiceImpl,cdWarehouseServiceImpl,cdWhCustomerServiceImpl,cdWhItmeServiceImpl,cdWhLocAreaServiceImpl,cdWhLocationServiceImpl,wmStockAdjustServiceImpl,wmStockFreezeServiceImpl,wmStockReleaseServiceImpl,wmStockServiceImpl,esMenuFunctionsServiceImpl,esMrRightsServiceImpl,esMuRightsServiceImpl,WMWareHouseStatServiceImpl,esDictionaryServiceImpl,esDictionaryTypeServiceImpl,esExceptionServiceImpl,esIconsServiceImpl,esMenuServiceImpl,esPropertiesServiceImpl,esRoleServiceImpl,esUserServiceImpl,wmIntoOrderBatchCodenoServiceImpl,wmIntoOrderinfoServiceImpl,wmIntoOrderServiceImpl,wmReceiptServiceImpl,wmReturnInfoServiceImpl,wmInventorySheetDetailServiceImpl,wmInventorySheetServiceImpl,wmWarehouseMoveServiceImpl,ebInterfaceLogServiceImpl,ebIntoStockLogServiceImpl,ebOperateLogServiceImpl,ebOutStockLogServiceImpl,ebSysLogServiceImpl,wmBatchPickingServiceImpl,wmOutOrderDetailServiceImpl,wmOutOrderServiceImpl,APIForOMSServiceImpl,APIServiceImpl,corporationServiceImpl,esSaasServiceInfoServiceImpl,JZTDAPIServiceImpl,padServiceImpl,pdaApiImpl,quartzJobServiceImpl,statisticalChartsServiceImpl,stockWarringJobServiceImpl,syncOrderStutusServiceImpl,timerTaskServiceImpl,reportServiceImpl,wmItemDailyReportServiceImpl,cdWhUnpickServiceImpl,settingsServiceImpl,updateProductThead,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,dataSource,sqlSessionFactory,sqlSession,org.mybatis.spring.mapper.MapperScannerConfigurer#0,transactionManager,txAdvice,org.springframework.aop.config.internalAutoProxyCreator,pc,org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0,InitSysProperties,DailyTaskJob,DailyTaskJobMethod,DailyTaskCronTriggerBean,DailyTaskJobMethodSaas,DailyTaskCronTriggerBeanSaas,StockWarringTaskJob,StockWarringTaskJobMethod,StockWarringTaskCronTriggerBean,CycleSendInterfaceInfoTaskJob,CycleSendInterfaceInfoTaskJobMethod,CycleSendInterfaceInfoTaskCronTriggerBean,SpringJobSchedulerFactoryBean,taskExecutor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,wmStockAlertRuleMapper,wmWarringInfoMapper,cdCustomerMapper,cdWarehouseMapper,cdWhItmeMapper,cdWhLocAreaMapper,cdWhLocationMapper,wmStockAdjustMapper,wmStockFreezeMapper,wmStockMapper,wmStockReleaseMapper,esMenuFunctionsMapper,esMrRightsMapper,esMuRightsMapper,esDictionaryMapper,esDictionaryTypeMapper,ebUserWarehouseMapper,esExceptionMapper,esIconsMapper,esMenuMapper,esPropertiesMapper,esRoleMapper,esUserMapper,wmIntoOrderBatchCodenoMapper,wmIntoOrderCodenoMapper,wmIntoOrderInfoMapper,wmIntoOrderMapper,wmReceiptInfoMapper,wmReturnInfoMapper,wmInventorySheetDetailMapper,wmInventorySheetMapper,wmWarehouseMoveCodenoMapper,wmWarehouseMoveMapper,ebInterfaceLogMapper,ebIntoStockLogMapper,ebOperateLogMapper,ebOutStockLogMapper,ebSysLogMapper,wmAssignedPickcarMapper,wmBatchPickingMapper,wmOutOrderCodenoMapper,wmOutOrderDetailMapper,wmOutOrderMapper,wmStockAssignedMapper,corporationMapper,esSaasServiceInfoMapper,statisticalChartsMapper,wmItemTransferMapper,reportMapper,wmDailyItemReportMapper,settingsMapper,wmUnpickMapper]; root of factory hierarchy
2016-08-01 14:21:30,880 [pool-1-thread-6] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10005)新增組織測試預警資訊選單沒有庫存記錄!!!
2016-08-01 14:21:30,884 [Thread-4] INFO  [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Shutting down Quartz Scheduler
2016-08-01 14:21:30,884 [Thread-4] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED shutting down.
2016-08-01 14:21:30,884 [Thread-4] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED paused.
2016-08-01 14:21:30,884 [pool-1-thread-5] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10004)測試新增組織沒有庫存記錄!!!
2016-08-01 14:21:30,885 [pool-1-thread-9] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-08-01 14:21:30,885 [pool-1-thread-9] DEBUG [java.sql.Connection] - ==>  Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10008 st LEFT JOIN cd_wh_itme_10008 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-08-01 14:21:30,885 [pool-1-thread-9] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-08-01 14:21:30,888 [pool-1-thread-3] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10002)test沒有庫存記錄!!!
2016-08-01 14:21:30,888 [pool-1-thread-7] DEBUG [java.sql.Connection] - ooo Using Connection [[email protected]]
2016-08-01 14:21:30,888 [pool-1-thread-7] DEBUG [java.sql.Connection] - ==>  Preparing: SELECT cd.CDSK_ITEM_CODE ProductCode,st.WMST_NOW_NUMBER ProductNum,st.WMST_ENABLED_NUMBER AvailableProductNum,st.WMST_SKU_UNIT ProductUnit FROM wm_stock_10006 st LEFT JOIN cd_wh_itme_10006 cd ON cd.CD_ITEM_ID=st.WMST_SKU_ID GROUP BY st.WMST_SKU_NAME,st.WMST_SKU_UNIT 
2016-08-01 14:21:30,892 [pool-1-thread-7] DEBUG [java.sql.PreparedStatement] - ==> Parameters: 
2016-08-01 14:21:30,895 [Thread-4] INFO  [org.quartz.core.QuartzScheduler] - Scheduler SpringJobSchedulerFactoryBean_$_NON_CLUSTERED shutdown complete.
2016-08-01 14:21:30,896 [Thread-4] INFO  [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] - Shutting down ExecutorService 'taskExecutor'
2016-08-01 14:21:30,900 [Thread-4] INFO  [com.alibaba.druid.pool.DruidDataSource] - {dataSource-1} closed
2016-08-01 14:21:30,901 [pool-1-thread-9] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10008)測試新增專用組織沒有庫存記錄!!!
2016-08-01 14:21:30,903 [pool-1-thread-7] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10006)test1沒有庫存記錄!!!

庫存多執行緒操作查詢:

2016-08-01 14:42:21,468 [pool-1-thread-5] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10004)測試新增組織沒有庫存記錄!!!
2016-08-01 14:42:21,468 [pool-1-thread-7] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10006)test1沒有庫存記錄!!!
2016-08-01 14:42:21,471 [pool-1-thread-2] ERROR [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>>>>>>>>>>>>>>有庫存。。。。。。。。。。。。tenantCode:10001
2016-08-01 14:42:21,471 [pool-1-thread-3] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10002)test沒有庫存記錄!!!
2016-08-01 14:42:21,468 [pool-1-thread-8] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10007)aaabbbbbb沒有庫存記錄!!!
2016-08-01 14:42:21,475 [pool-1-thread-4] ERROR [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>>>>>>>>>>>>>>有庫存。。。。。。。。。。。。tenantCode:10003
2016-08-01 14:42:21,470 [pool-1-thread-6] INFO  [com.wlyd.fmcgwms.service.basic.impl.WmStockServiceImpl] - >>>>組織(10005)新增組織測試預警資訊選單沒有庫存記錄!!!
2016-08-01 14:42:21,479 [Thread-4] INFO  [com.alibaba.druid.pool.DruidDataSource] - {dataSource-1} closed

注:第5點中,實際問題是因為我自己少寫了start()而不自知,所以才寫了第5點的嘗試,實際上完全沒有必要,平時程式設計的時候還是注意點,避免走不必要的彎路。

實際上Spring提供了一個批處理的工具spring-batch 有興趣的可以研究研究,可以替代上面的方案。

相關推薦

Spring事務執行處理-解決方案

首先,Spring Ioc 依賴注入的就是單例物件,我們在使用的時候如果有多個相同處理且不怎麼耗時的情況下一般會採用for迴圈直接執行,這樣的情況下即使有事務管理也不會影響業務執行下去;但是,大多數的應用比如:系統與系統之間的互動就比較耗時了,此時使用for迴圈執行業務就不

NodeJS執行解決方案 -- pm2 之一

寫在前面這兩年做了很多Web的前後端開發,也有一些經驗,所以在這裡分享一下。很久不寫部落格了,因為很多東西都用evernote來記錄了,方便快捷。然後業餘我也做了一個單頁網站,基於AngularJS+N

Spring-Boot中如何使用執行處理任務

看到這個標題,相信不少人會感到疑惑,回憶你們自己的場景會發現,在Spring的專案中很少有使用多執行緒處理任務的,沒錯,大多數時候我們都是使用Spring MVC開發的web專案,預設的Controller,Service,Dao元件的作用域都是單例項,無狀態,然後被併發

Spring事務管理執行的困惑

由於Spring的事務管理器是通過執行緒相關的ThreadLocal來儲存資料訪問基礎設施(也即Connection例項),再結合IoC和AOP實現高階宣告式事務的功能,所以Spring的事務天然地和執行緒有著千絲萬縷的聯絡。    我們知道Web容器本身就是多執行緒的,W

java swing執行處理情況下UI假死的解決

背景&問題專案中使用java swing做了個多執行緒處理任務的介面,在介面上顯示多執行緒任務的log資訊,為了實時顯示log資訊,使用了log4j的org.apache.log4j.WriterAppender並單獨開了執行緒。但是log資訊只在多執行緒任務結束後才

spring執行事物解決辦法

1、最近做專案使用了多線,但是發現多執行緒事務無法起作用,就是多執行緒執行時每個執行緒的方法雖然加了事務的註解但是資料插入依舊不會回滾2、此時主執行緒操作資料插入事物是起作用的。springboot 解決辦法    先獲取spring的context    配置中 新增事物管

執行處理慢sql查詢小筆記~

多執行緒處理慢sql查詢以及List(Array)的拆分 系統資料量不大,但是訪問速度特別慢,使用多執行緒優化一下!!! 優化結果:訪問時間縮短了十幾秒  25s --> 8s 一、List的拆分:Iterables.partition 注意: 引入的包為google名下的   &n

HTML5學習之WebWork執行處理

  多執行緒技術在服務端技術中已經發展的很成熟了,而在Web端的應用中卻一直是雞肋 在新的標準中,提供的新的WebWork API,讓前端的非同步工作變得異常簡單。 使用:建立一個Worker物件,指向一個js檔案,然後通過Worker

執行處理list

package com.zhx.web.invoice.service; import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import

FMDB使用,事務執行,加密等比較全面的用法。

一:簡單使用 既然FMBD是對資料庫的封裝,那基本功能應該包括 增、刪、改、查。 主要使用到的類為FMDatabase(資料庫)FMResultSet(查詢的結果)。 其中增、刪、改,三個方法都是使用FMDatabase類的executeUpdate方法也就是都算作資料的更新, 而查

python 執行處理佇列

轉載自: https://blog.csdn.net/u011655220/article/details/79037032 from threading import Thread import time import random from queue import Queue from co

[SimplePlayer] 7. 執行處理

在前面的文章中,我們分別實現了視訊影象解碼、播放,音訊解碼、播放,現在則需要把這些功能組合起來。總體上來說,整個程式的功能可以分為兩條線路:視訊以及音訊,兩條線之間除了後續的同步操作之外基本沒有任何關聯。而線上路當中,各個模組之間並沒有太緊密的耦合,只要上游模組提供了原料,下游模組就可以執行處理。因此,我們可

IOS儲存張圖片 執行處理

儲存多張圖片的時候,既要控制不丟圖片,又要控制圖片可以多執行緒。提高儲存速度,防止程式崩潰,防止使用者等待時間過久 這裡我們可以使用Photos框架的PHPhotoLibrary類,這個可以幫助你多執行緒儲存圖片 -(void)saveBtn { [SSGOTools againRe

通過執行處理提高Redis效能

Redis通常被稱為單程序單執行緒模型。 這不是真的! Redis還執行多個後端執行緒來執行後端清理工作,例如清理髒資料和關閉檔案描述符。在Redis中,主執行緒負責主要任務,包括但不限於:接收來自客戶端的連線,處理連線讀/寫事件,解析請求,處理命令,處理定時器事件和同步資料。只有一個CPU核心執行單個程

Spring定時任務執行

  單執行緒 1)在Spring.xml中開啟定時器的功能 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml

python DLib實時性不夠,通過執行解決

# created at 2017-11-27 # updated at 2018-09-06 # Author: coneypo # Dlib: http://dlib.net/ # Blog: http://www.cnblogs.com/AdaminXie/ # Gi

python 執行處理IO操作

from threading import Thread 方法1 t = Thread(target=func, args=(1,)) t.start() 方法2 clasee MyT

Spring高階話題-執行-TaskExecutor

分析 在Spring中,通過任務執行器,也就是TaskExecutor來實現多執行緒和併發程式設計。 使用ThreadPoolTaskExecutor可實現一個基於執行緒池的TaskExecutor。 而實際開發中任務一般是非阻礙的,也就是非非同步的,所以

spring中使用執行ThreadPoolTaskExecutor

業務需要,在進行更新的時候會執行一系列操作,或者說更新時會有一個通知.但是沒有使用訊息佇列.所以我想用多執行緒來實現這個功能.最開始沒有使用執行緒池.使用的是內部類的形式實現,程式碼為: /** * create by : * description: 開啟接單

Python下的執行處理

########多執行緒######### ## 執行緒的概念與多執行緒的引入     一個標準的執行緒由執行緒ID,當前指令指標(PC),暫存器集合和堆疊組成。另外,執行緒是程序中的一個實體,一個程序裡面必然會有一個主執行緒,是被系統獨立排程和分派的基本