2012-08-29 69 views
3

我們試圖實現一種我們的應用程序的多線程部分和數據庫訪問之間ensurance,使DB不會有太多的線程被擊中(客戶要求時保持活着),同時使系統的其他部分充分利用必要的線程數量。智能方式ThreadPoolTask​​Executor類測試

設計似乎工作(春天批處理分區+使用ThreadPoolTask​​Executor處理數據訪問),但問題是與測試設計(基於http://helenaedelson.com/?p=432)。

現在我必須將Thread.sleep(4000)添加到我的單元測試中,以確保在產生的額外線程有變化完成工作之前,Spring上下文不會從測試下被終止並且返回值返回到主線程。

會有人對如何使這個測試implementastion更聰明一些更好的想法嗎?

測試儀:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({ "classpath:partitionJdbcJob.xml" }) 
@DirtiesContext(classMode = ClassMode.AFTER_CLASS) 
public class TaskTests { 
protected static final Logger logger = LoggerFactory.getLogger(TaskTests.class); 

@Autowired 
private OrderServiceImpl orderService; 

@Test 
public void testExecution() { 
    logger.info("Starting execution thread..."); 

    for (int i = 0; i < 8; i++) { 
     orderService.dispatch(); 
    } 

    try { 
     // So that spring context is not destroyed from under the multi-threaded runnables 
     Thread.sleep(4000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

}

測試服:

@Service("orderServiceImpl") 
public class OrderServiceImpl { 
protected static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class); 

@Resource(name = "beanTaskExecutor") 
private TaskExecutor taskExecutor; 
// private AsyncTaskExecutor taskExecutor; 

CompletionService completionService; 

@Autowired 
public void OrderServiceImpl(DataSource dataSource) { 
    completionService = new ExecutorCompletionService(taskExecutor); 
} 

public void dispatch(final RetailPriceOptimization order) { 
    logger.info("Starting dispatch execution..."); 

    if (this.taskExecutor != null) { 
     logger.info("taskExecutor found..."); 
     this.taskExecutor.execute(new Runnable() { 
      public void run() { 
       withExecutor(order); 
      } 
     }); 
    } 

    try { 
     Object future1 = completionService.take().get(); 
     Object future2 = completionService.take().get(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } 
    logger.info("Completed dispatch execution..."); 
} 

private void withExecutor(final RetailPriceOptimization order) { 
    logger.info("Starting withExecutor execution..."); 

    Object result1 = completionService.submit(new Callable<String>() { 
     public String call() { 
      return findById("0000dd2gsl1u1546"); 
     } 
    }); 
    Object result2 = completionService.submit(new Callable() { 
     public Object call() { 
      return orderDao.find(new Long("16")); 
     } 
    }); 
} 

}

回答

0

現在您的測試看來,因爲你所呼叫的completionService .take()是同步的兩倍內該dispatch(...)方法。該take()將等待,直到作業完成。所以當我閱讀它時,你根本不需要睡覺。

另外,我沒有看到的CompletionService在所有的需要。你應該只保留2個期貨,然後要求他們get(...)一次一個。好像你正在等待2個電話完成,他們將同時運行。 CompletionService只有當你可以立即開始處理其中一個結果時纔有用。

0

你不試圖重構你的服務一點點。

@Service 
public class ConcurrentService{ 

    public Map<String, Object> createList(){ 
     this.asynCall(); 
    } 

    @Async("taskExecutor") 
    private Future<Map<String, Object>> asynCall(){ 
      //I will use submit instead of execute 
      return this.taskExecutor.submit(new Callable(){ 
       //Override the proper logic following interface 
      }) 
    ..... 
    } 

} 

對於所有要在並行使用,以執行新的方法遵循與@Async,這使它異步執行它,在你使用合併迴應或者只是使用的一個方法的過程開始並行處理,使用Future API等待作業isDone。

布爾isDone()如果此任務完成,則返回true。完成的可能是 是由於正常終止,例外或取消 - 在這些情況下全部爲 ,此方法將返回true。

這將使等待所有的期貨完成

while(future1.isDone() future2.isDone()){ 
//Do Something in the meanwhile 
} 
//Code will start the execution once both process are completed 

您可以構建一個包裝方法,使更容易和更動態地等待completition。

Spring配置做到這一點是:

<task:annotation-driven executor="taskExecutor" mode="aspectj" /> 

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> 
    <property name="corePoolSize" value="50" /> 
    <property name="maxPoolSize" value="300" /> 
    <property name="queueCapacity" value="30" /> 
</bean> 

而且對我來說這是集成測試,使用您的真實對象和服務,上面的配置將導致測試所有的業務邏輯正確執行,並將等到所有的進程都齊全,所以你不會需要有一個了Thread.sleep,在你的榜樣的方法執行後>

orderService.dispatch(); 

您將能夠創建列表的斷言,以驗證過程按預期工作,不要忘記這是一個部分測試目的。

相關問題