コマンドパターンを使用してみてください。
class MyServiceManager {
public void execute(MyServiceTask tasks...) {
// set up everyting
MyService service = this.acquireService();
// execute the submitted tasks
foreach (Task task : tasks)
task.executeWith(service);
// cleanup yourself
service.releaseResources();
}
}
これにより、リソースの取得と解放を完全に制御できます。呼び出し元はタスクをサービスに送信するだけで、ユーザー自身がリソースを取得してクリーンアップする責任があります。
ただし、キャッチがあります。呼び出し元はこれを行うことができます:
MyServiceTask t1 = // some task
manager.execute(t1);
MyServiceTask t2 = // some task
manager.execute(t2);
ただし、この問題が発生した場合は対処できます。パフォーマンスの問題があり、一部の呼び出し元がこれを実行していることがわかった場合は、単に適切な方法を示して問題を解決します。
MyServiceTask t1 = // some task
MyServiceTask t2 = // some task
manager.execute(t1, t2);
他のタスクに依存するタスクのプロミスを実装することにより、この意的に複雑にすることができますが、その後、ものをリリースすることもより複雑になります。これは出発点にすぎません。
非同期
コメントで指摘されているように、上記は非同期リクエストでは実際には機能しません。そのとおりです。しかし、これは、Java 8ではCompleteableFutureを使用して簡単に解決できます。特にCompleteableFuture#supplyAsync
、個々の先物を作成し、すべてのタスクが完了したらCompleteableFuture#allOf
リソースのリリースを実行します。あるいは、常にThreadsまたはExecutorServicesを使用して、Futures / Promisesの独自の実装をロールバックできます。