4

アプリケーションのマルチスレッド部分とデータベースアクセスの間に一種の保証を実装して、DBがあまりにも多くのスレッド(顧客の要件)に見舞われないようにすると同時に、システムの他の部分を完全に利用できるようにしようとしています。必要な量のスレッドで。

デザインは(SpringBatchパーティショニング+ThreadPoolTask​​Executorを使用したデータアクセスの処理)で機能するようですが、問題はデザインのテストにあります(http://helenaedelson.com/?p=432に基づく)。

今のところ、単体テストにThread.sleep(4000)を追加して、生成された追加のスレッドが作業を終了して戻り値を返すように変更する前に、テストの下からSpringコンテキストが強制終了されないようにする必要がありました。メインスレッドに。

このテストの実装をよりスマートにする方法について、誰かがより良いアイデアを持っていますか?

テスター:

@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"));
        }
    });
}

}

4

2 に答える 2

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。

boolean isDone()このタスクが完了した場合に true を返します。完了は、正常終了、例外、またはキャンセルが原因である可能性があります。これらすべての場合において、このメソッドは true を返します。

これにより、すべての先物が完了するのを待つことができます

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

ラップ メソッドを作成して、完了をより簡単かつ動的に待機させることができます。

それを行うための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>

また、これは実際のオブジェクトとサービスを使用するための統合テストです。上記の構成により、すべてのビジネス ロジックでテストが正しく実行され、すべてのプロセスが完了するまで待機するため、スレッドは必要ありません。あなたの例でメソッドを実行した後、スリープ>

orderService.dispatch();

アサートのリストを作成して、プロセスが期待どおりに機能していることを確認できます。これはテスト目的の一部であることを忘れないでください。

于 2015-09-13T19:20:05.960 に答える