2016-11-22 5 views
3

私は、Java Webアプリケーションのバックエンドで作業します。大きなデータ検索を高速化するためにいくつかのマルチスレッドを追加しました。プロセスで作成したExecutorServicesをいくつか使用しました。しかし、私は、Webアプリケーションでこのようにスレッドを作成するのは良い考えではないかもしれず、 'com.ibm.websphere.asynchbeans.WorkManager'はおそらくオプションであるかもしれないと読んだことがあります。しかし、バックエンドで使うのはあまり面白くないようです。ドキュメントによれば、作業マネージャは「非同期Beanを使用するJava Platform、Enterprise Edition(Java EE)アプリケーション用に作成されたスレッドプール」です。私は、非常にフロントエンドの無知なバックエンドの男として、豆が何であるか全く知らない。仕事マネージャが私の望むものではないようですが、実際にExecutorServiceを手動で作成することは実際には悪い考えですが、最良のアプローチが何であるかはわかりません。バックエンドでマルチスレッドにWorkManagerを使用する必要がありますか?

+0

私はプール内の固定数のスレッドを持つExecutorサービスを作成することをお勧めします。たとえば、スレッドを作成する必要があるたびに、このシングルトンクラスを呼び出してこのタスクを渡しますそれを実行する実行者サービス。そうすれば、多くのスレッドプールを作成することはなくなりますが、1つのスレッドプールを共有することになります。 –

+0

さらに、現在のシステム仕様/容量をポーリングし、パフォーマンスを最適化するためにこのThreadpool/Singleton実行プログラムを構成することができます。 – n247s

+0

@ BandiKishore、@ n247s OPは、一般にWebコンテナにスレッドを作成するのがよいかどうかについて質問します。 –

答えて

3

Webアプリケーションのバックエンドに独自のスレッドを作成することは、次の理由から悪い考えです。アプリケーションサーバーコンテナがスレッドを管理します。だからあなたがあなたのアプリケーションに独自のスレッドを作成する場合、コンテナはそれらについて知りませんし、それらを管理することができなくなります。したがって、スレッドを誤って管理すると、アプリケーションがメモリリークやその他のスレッド関連の問題を引き起こす可能性があります。理論的には、アプリケーションサーバーにスレッドプールを登録し、JNDIを使用してコンテナからスレッドをリクエストするのが最善の方法です。しかし、それは過度の可能性があります。だから時には自分のスレッドを管理したいかもしれません。したがって、この場合はExecutorServiceがスレッドを管理するための非常に優れたAPIを提供するため、最良の方法です。あなたのアプリケーションがシャットダウンしたら、ExecutorServiceをシャットダウンして、孤立したスレッドが残っていないことを確認してください。あなたがそれに注意するならあなた自身のスレッドを作成することができます。控えめに使用してください。完了したら、またはアプリケーションがシャットダウンしたときには、ExecutorServiceをシャットダウンするように注意してください。ところで、ThreadLocal変数にも同様の問題があります。完了したら、metod remove()を絶対に呼び出さなければなりません。そうしないと、アプリケーションがシャットダウンしてもメモリに残り、Application Serverの再起動だけがクリアされます。これは危険なメモリリークです。

1

ただ、かなり良い説明ですマイケルGantmanの答え、上で展開して、コンテナがあなたのスレッドプールを管理できるようにするのJavaEEアプローチは、実際に実装する超簡単です:

@Stateless 
public class Foo { 

    @Asynchronous 
    @Override 
    public void doSomething() { 
     //all calls to this function are asynchronous 
    } 
} 

@Aysnchronousは魔法の世話をしますここでは、この関数を非同期に呼び出す必要があることをコンテナに指定し、それが何を意味するのかはコンテナの責任です。その後、同様に簡単です、あなたの関数を実行するために、あなたのコンテナ管理スレッドプールに呼び出す:

@Stateless 
public class Bar { 
    @EJB 
    Foo myFooEJB; 

    public void businessMethod() { 
     myFooEJB.doSomething(); 
    } 
} 

チェックアウトはこれらより読み込みのために:javax.ejb.AsynchronousAsynchronous method invocation

<thread-pools> 
    <thread-pool name="poolName"> 
     <max-threads count="10"/> 
     <keepalive-time time="100" unit="milliseconds"/> 
    </thread-pool> 
</thread-pools> 
:私はあなたがIBM製品を使用している知っているので、具体的にあまりにも多分少しの取得、JBossの中で、あなたの非同期 poolNameのようなプールを参照する必要がありますどこ <async thread-pool-name="poolName"/>https://docs.jboss.org/author/display/WFLY8/EE+Subsystem+Configuration) を指定することで、サブシステム構成の一部として提供されます

しかし、あなたは、提出するコンテナで管理することができExecutorServiceにちょうどいくつかのタスクしようとしている場合は、より良い方法があります:実行し、私はここに参照をした特にこと、

@Resource 
ManagedExecutorService executorService; 

@Resource 
ManagedScheduledExecutorService scheduledExecutorService; 

java.io.PrintWriter out = ...; 

void scheduleSomeStuff(){ 
    scheduledExecutorService.schedule(new Runnable() { 
     @Override 
     public void run() { 
      out.println("Print out after roughly 15 seconds.") 
     } 
    }, 15, TimeUnit.SECONDS); 

    executorService.submit(new Callable<Boolean>() { 
     @Override 
     public Boolean call() throws Exception { 
      out.println("Print only once, when the task is run by the executor service's discretion."); 
     } 
    }; 
} 

これら2つのリソースは、別のスレッドプールでここでは、もともと私はexecutorとして@Asynchronousスレッドプールを使用してここに何かを投稿しましたが、コンテナにはすでにあなたのためのものがあるはずなので、不要です。それで今ここに見られる更新された答え。

これもまたJBossに固有のものですが、JBossではこれはサブシステムmanaged-scheduled-executor-servicesmanaged-executor-servicesとして構成されています。これらの2つのサブシステムには、それぞれ独自のスレッドプールがあります。

関連する問題