同期メソッドを使用するか、Spring @transactional を使用しますか?
-
21-09-2019 - |
質問
電子メールを送信するために使用されるメソッドがあります。このメソッドをロックして、一度に 1 つのスレッドだけがアクセスできるようにし、残りのスレッドは同時にプールしたいと考えています。メソッドを同期するか、Spring @transactional PROPAGATION_REQUIRED を使用する必要がありますか?
私のサービス層では
//each time use new thread to send out email
public void sendThroughSMTP(List<String> emails,String subject,String content){
//each time will open and sent through port 25. dont u think this will caused too many threads spawned?
BlastEmailThread blastEmailThread = new BlastEmailThread(emails,subject,content);
blastEmailThread.start();
}
解決
インスタンスレベルのものを一切使用せずに、メソッドをスレッドセーフにしてみてはいかがでしょうか?
ただし、Spring のトランザクション管理がここにどのように適合するのかわかりません。つまり、Spring にはトランザクション マネージャーがほとんど提供されていません。 DataSourceTransactionManager
, JtaTransactionManager
, HibernateTransactionManager
これはすべてデータベースの永続性に関するものです。このメールの送信には何を設定しますか?
まず、そもそもなぜスレッドの安全性を心配するのかを示す必要があると思います。おそらく、関連するコード スニペットか何かを見せたいと考えているでしょう。そうすれば、何かご提案できるかもしれません。
【追記】
そのメソッドを呼び出すたびにスレッドを生成し、状態から何も使用しない場合、なぜそのメソッドを作成する必要があるのか synchronized
. 。メソッドを同期しても、スレッドの数はまったく制限されません。同期のため、新しいスレッドを開始する前に前のスレッドが作業を完了している可能性があります。スレッドを生成するプロセスが遅くなる可能性があります。
ただし、実際に多くのスレッドが実行されていてメモリが不足することが判明するまでは、これを使用する必要があります。そして、時間内に本当にそれに取り組みたい場合は、次のようなブロックメカニズムを選択する必要があります。 セマフォ.
他のヒント
別の可能性は、JMSキューを使用し、豆(または春JMS経由)メッセージ駆動型のコードを送信する電子メールを置くことであろう。あなたは、あなたのMDBの多くの同時インスタンスをどのように使用するかを制御するために、あなたのアプリケーションサーバーを使用し、そのように送信メールを絞ることができます。
SPING 3.0であなたは、タスクの実行を行うために@Asyncアノテーションを使用することができます。
@Async
public void sendThroughSMTP(List<String> emails,String subject,String content){
//Send emails here, you can directly send lots of email
}
は、アプリケーションのコンテキストで次のように指定して、タスクスキーマのためのxmlnsを追加することを忘れないでください。
あなたが一定時間実行を遅延する場合、あなたはあなたの方法に@Scheduledのアノテーションを使用することができます。
@Asyncと@Scheduledに関する詳しいチュートリアルでは、ここで見つけることができます:
ます。http://ブログ.springsource.com / 2010/01/05 /タスクスケジューリングの簡素化・イン・スプリング3-0 / の
それがあなたの質問に答えているかどうかはわかりませんが、メールごとに新しいスレッドを作成して start を呼び出す代わりに、 執行者 または ExecutorService クラスのメンバーとして、実装として使用できます。 スレッドプールエグゼキュータ プールサイズは1です。sendMail メソッドは、Runnable をエグゼキューターに送信します。
春@Transactionalは、あなたのケースで使用される非常に正確ではありません。最善の策はsynchorized方法を使用して、あなたの方法は、数百時間で呼び出された場合プーリングいくつかのスレッドを追加しています。しかし、私はあなたがここにスレッドプールを必要といけないと思います。
あなたはブラスト電子メールを送信するためにスレッドを使用する場合は、、その後、メソッドを同期何を指すのか?一つのプロセスは、あなたのメソッドを呼び出すと、電子メールを送信する場合、他のプロセスがまだ完了していない、あなたの方法でも最初のメール送信プロセスを呼び出します。
電子メールの送信プロセスを絞るために、あなたが意図した場合は、キュー(コレクション)condiderと同期ブロックでコレクションを保護する必要があります。任意の項目がある場合は、電子メールの送信処理に進み、キュー内の1つの項目がある場合は、そのキューを監視し、それをポップし、ブラスト電子メールを送信し、電子メールのプロセスの終了を送信するまで待ってから再度キューをチェックするために、別のプロセスを作成します。キューにアイテムが、時間のいくつかのチャンクのモニター・スレッドのスリープをしない場合には、スリープ時間がある場合は、再度キューをチェックし終えています。
あなたのサービスsingleton
を作成し、あなたの方法にsynchronized
を追加します。