一度CountDownLatchをSpringBootで@Asyncに合わせて使用することを記す
2290 ワード
需要
プロジェクトはspringbootを使用し、サードパーティインタフェースを呼び出すたびにローカルデータのフィールドをクエリー条件として使用するシーンがあります.ベンダーが提供するインタフェースは、単一のクエリーのみであるため、ローカルからクエリーされたデータを巡回してインタフェースを呼び出すしかありません.これにより、応答時間が遅く、効率が低下します.
では、最適化方法を考えてみましょう.まず、マルチスレッドを有効にして、ローカル・データベースからクエリーされたレコードごとにサードパーティ・インタフェースを並列に呼び出すことができます.
まず、サードパーティインタフェースを呼び出し、データを埋め込むスレッドタスククラスを新規作成し、springの@Async注釈で非同期呼び出しを実現します.擬似コードは次のとおりです.
サービス層ループコール
これにより非同期リクエストインタフェースが実現され,効率が大幅に向上した.しかし、非同期呼び出しのため、データがまだ埋め込まれていないと返されます.これは明らかに私たちが望んでいる効果ではありません.AsyncTaskのすべてのスレッドが終了するのを待ってから、現在のスレッドタスクを呼び出す方法を返さなければなりません.そこでJDK 1を思い出した.5バージョン以降に提供されるカウンタCountDownLatch(CountDownLatchの使い方については本稿では述べないが、初めて使用して記録しただけで、間違ったところがあればアドバイスしてほしい).
考え方:
サービス層のメソッドでCountDownLatchをインスタンス化し、スレッド数を設定します.スレッド数は、ローカル・データベースからクエリされたlistの長さであり、スレッド・タスクに転送され、各スレッドが実行されるとcountDown()メソッドが呼び出されます.最後に、サービスレイヤでawait()メソッドを呼び出します.これにより、スレッドカウントがゼロになるまで、サービスのスレッドは待機します.
Service:
AsyncTask:
これで問題が解決する.
プロジェクトはspringbootを使用し、サードパーティインタフェースを呼び出すたびにローカルデータのフィールドをクエリー条件として使用するシーンがあります.ベンダーが提供するインタフェースは、単一のクエリーのみであるため、ローカルからクエリーされたデータを巡回してインタフェースを呼び出すしかありません.これにより、応答時間が遅く、効率が低下します.
では、最適化方法を考えてみましょう.まず、マルチスレッドを有効にして、ローカル・データベースからクエリーされたレコードごとにサードパーティ・インタフェースを並列に呼び出すことができます.
まず、サードパーティインタフェースを呼び出し、データを埋め込むスレッドタスククラスを新規作成し、springの@Async注釈で非同期呼び出しを実現します.擬似コードは次のとおりです.
@Component
public class AsyncTask {
/**
*
*/
@Async
public void queryTask(Entity entity){
Data data = doPost();
entity.setData(data);
}
}
サービス層ループコール
public class Service {
@Autowired
private AsyncTask asyncTask;
@Autowired
private EntityMapper mapper;
public List queryData(){
List list = mapper.selectAll();
for(Entity entity:list){
asyncTask.queryTask(entity);
}
return list;
}
}
これにより非同期リクエストインタフェースが実現され,効率が大幅に向上した.しかし、非同期呼び出しのため、データがまだ埋め込まれていないと返されます.これは明らかに私たちが望んでいる効果ではありません.AsyncTaskのすべてのスレッドが終了するのを待ってから、現在のスレッドタスクを呼び出す方法を返さなければなりません.そこでJDK 1を思い出した.5バージョン以降に提供されるカウンタCountDownLatch(CountDownLatchの使い方については本稿では述べないが、初めて使用して記録しただけで、間違ったところがあればアドバイスしてほしい).
考え方:
サービス層のメソッドでCountDownLatchをインスタンス化し、スレッド数を設定します.スレッド数は、ローカル・データベースからクエリされたlistの長さであり、スレッド・タスクに転送され、各スレッドが実行されるとcountDown()メソッドが呼び出されます.最後に、サービスレイヤでawait()メソッドを呼び出します.これにより、スレッドカウントがゼロになるまで、サービスのスレッドは待機します.
Service:
public class Service {
@Autowired
private AsyncTask asyncTask;
@Autowired
private EntityMapper mapper;
public List queryData(){
List list = mapper.selectAll();
CountDownLatch latch = new CountDownLatch(list.size());
for(Entity entity:list){
asyncTask.queryTask(entity,latch);
}
latch.await();
return list;
}
}
AsyncTask:
@Component
public class AsyncTask {
/**
*
*/
@Async
public void queryTask(Entity entity,CountDownLatch latch){
Data data = doPost();
entity.setData(data);
latch.countDown();
}
}
これで問題が解決する.