出典:https://blog.csdn.net/kity9420/article/details/80740466
序文には
、多くの場合、このようなインターフェースを呼び出すなど、いくつかのパフォーマンスの問題に遭遇、あなたはサイクルを100回呼び出したい、との結果を返すようにすべてのコールを取得する必要があり、我々は通常、シリアルループの時のために配置され、これを呼び出します一つは、この問題を解決する方法を、次に、どのようにゆっくりと道路の方法を想像することができますか?
マルチスレッド
この問題を解決するために、私はマルチスレッドを使用しています方法。、Runnableインタフェースを実装トレッドクラスを継承する2つの従来のマルチスレッドの実装が、2つの実装がありますが、一般的な問題があり、それは何の戻り値はありません、私たちは各スレッドの戻り値を取得するために、それは、私が呼び出し可能とThreadPoolExecutor使うクラスや、Runnableインタフェースをトレッドすることはできませんので、非常に難しい問題であり、かつ、呼び出し可能な方法は、プロセスが義務に戻り、invokeAllのThreadPoolExecutorや結果のスレッドを得ることができる方法を提出することができます
ケースは、
ユーザが必要と想定されるメッセージ100を送信し、各ユーザの結果のニーズを返し、コードの構造を見
CallableTemplate.java
パッケージcom.gdut.thread.multiThread; インポートjava.util.concurrent.Callable; / ** *テンプレートベースのマルチスレッド * @author yang.han * * @param <V> * / パブリック 抽象 クラス CallableTemplate <V> を実装呼び出し可能<V> { / ** *前処理、サブクラスはこのメソッドをオーバーライドすることができる * / 公共 ボイドbeforeProcess(){ (System.out.printlnは "処理前" ); } / ** ビジネス・ロジックを処理するための方法が必要*サブクラスがオーバーライドする * @param <V>を *@return * / パブリック 抽象Vプロセス(); / ** *后置处理、子类可以オーバーライド该方法 * / パブリック 無効afterProcess(){ System.out.printlnは( "処理後" )。 } @Override パブリック Vコール()スロー例外{ beforeProcessを(); V結果 = プロセス(); afterProcess(); 戻り値の結果; } }
呼び出し可能CallableTemplateクラスは、インターフェイスを実装し、処理方法を実装し、クラスは抽象クラスであり、戻り値の任意のタイプを受信beforeProcess前処理方法、抽象サービスロジック方法afterProcess後処理、特定のプロセス、サブクラスで実装される方法
IConcurrentThreadPool.java
パッケージcom.gdut.thread.multiThread; 輸入はjava.util.List; 輸入java.util.concurrent.ExecutionException。 パブリック インターフェースIConcurrentThreadPool { / ** *初始化线程池 * / ボイドinitConcurrentThreadPool(); / ** *提交单个任务 * @param <V> * @paramのタスク * @return * @throws InterruptedExceptionある * @throws ExecutionException * / <V> V(CallableTemplateは、<V>タスク)を提出スロー例外:InterruptedException、ExecutionException。 / ** *提交多个任务 * @param <V> * @paramのタスク * @return * @throws InterruptedExceptionある * @throws ExecutionException * / <V>リスト<V> invokeAll(リスト<?拡張 CallableTemplate <V >>タスクを)スローInterruptedExceptionある、ExecutionExceptionは、 }
IConcurrentThreadPoolマルチスレッドインタフェースクラス、三つの方法の評判、initConcurrentThreadPoolです:スレッドプールを初期化し、提出する:単一タスクスレッドを提出し、戻り値、invokeAll:スレッドの複数のタスクを提出し、返し値
ConcurrentThreadPool.java
パッケージcom.gdut.thread.multiThread; 輸入はjava.util.ArrayList; 輸入はjava.util.List; 輸入java.util.concurrent.ExecutionException。 輸入java.util.concurrent.Future。 輸入java.util.concurrent.LinkedBlockingDeque。 輸入java.util.concurrent.ThreadPoolExecutor。 輸入java.util.concurrent.TimeUnit。 パブリック クラス ConcurrentThreadPoolは実装IConcurrentThreadPool { プライベートThreadPoolExecutor threadPoolExecutorを。 // 核心线程数 プライベート int型 corePoolSize = 10 ; //最大线程数 プライベート int型 maximumPoolSize = 20 ; // 超时时间30秒 プライベート 長い keepAliveTimeが= 30 ; @Override 公共 ボイドinitConcurrentThreadPool(){ threadPoolExecutor = 新しいThreadPoolExecutor(corePoolSize、 maximumPoolSize、 keepAliveTimeが、 TimeUnit.SECONDS、 新しい LinkedBlockingDeque <Runnableを> () )。 } @Override 公共 <V> Vは、(CallableTemplate <V>タスク)が提出スローExecutionException {InterruptedExceptionあるの 未来 <V>結果= threadPoolExecutor.submit(タスク)。 リターンresult.get(); } @Override 公共 <V>リスト<V> invokeAll(?一覧< 延び CallableTemplate <V >>タスク)がスローInterruptedExceptionある、ExecutionException { リスト <今後の<V >> tasksResult = threadPoolExecutor.invokeAll(タスク)。 リスト <V> resultList = 新しいのArrayList <V> (); 未来:tasksResult){ resultList.add(future.get())。 } 戻りresultList。 } }
ConcurrentThreadPoolは、スレッドプールを実装するクラスを作成する方法を使用してinvokeAll ThreadPoolExecutorスレッドプールのクラスと、このクラスのメソッドを提出することでこれらの2つの方法の戻り値、getメソッド今後のクラスを介して使用できます
ICallableTaskFrameWork.java
パッケージcom.gdut.thread.multiThread; 輸入はjava.util.List; 輸入java.util.concurrent.ExecutionException。 パブリック インターフェースICallableTaskFrameWork { <V>リスト<V> submitsAll(?一覧< 延び CallableTemplate <V >> タスク) スローInterruptedExceptionある、ExecutionExceptionと、 }
ICallableTaskFrameWorkスレッドタスクフレームワークインタフェースが定義され、すべてのマルチスレッドの呼び出しは、このインタフェースを介して開始されます
CallableTaskFrameWork.java
パッケージcom.gdut.thread.multiThread; 輸入はjava.util.List; 輸入java.util.concurrent.ExecutionException。 パブリック クラス CallableTaskFrameWorkは実装ICallableTaskFrameWork { プライベート IConcurrentThreadPool concurrentThreadPool = 新しいConcurrentThreadPoolを(); @Override 公共 <V>リスト<V> submitsAll(?一覧< 延び CallableTemplate <V >> タスク) スローInterruptedExceptionある、ExecutionException { concurrentThreadPool.initConcurrentThreadPoolを(); リターン concurrentThreadPool.invokeAll(タスク)。 } }
CallableTaskFrameWorkはICallableTaskFrameWork実装クラスであり、submitsAllにsubmitAll実装に注目一私は手動でスレッドプールを初期化するメソッドを呼び出すスレッドプールオブジェクトIConcurrentThreadPoolインターフェースを呼び出すinvokeAll法によるマルチスレッドの呼び出しを開始するためのメソッドを実装concurrentThreadPool.initConcurrentThreadPool()は、実際のプロジェクトでは、アプリケーションがスレッドプールを初期化するために、このメソッドを呼び出すために開始しなければなりません
テストクラスコード
SendMessageService.java、これは電子メールのサービスクラスを送信するメッセージであることを前提としてい
パッケージcom.gdut.thread.multiThread; パブリック クラスSendMessageService { 公共 空のsendMessage(String型の電子メール、文字列の内容){ System.out.printlnは( "发送邮件..." ); } }
SendMessageHander.java、マルチスレッドメール送信処理クラス
パッケージcom.gdut.thread.multiThread; 輸入java.util.HashMapを; 輸入java.util.Map; パブリック クラス SendMessageHanderは拡張 CallableTemplate <地図<文字列、文字列>> { プライベート文字列の電子メールを、 プライベート文字列の内容。 公共SendMessageHander(文字列のメール、文字列の内容){ この .email = メール; この .content = コンテンツ; } @Override パブリックマップ<文字列、文字列> 工程(){ SendMessageService sendMessageService = 新しいですSendMessageService(); sendMessageService.sendMessage(電子メール、コンテンツ)。 地図 <文字列、文字列>マップ= 新しい HashMapの<文字列、文字列> (); map.put(電子メール、コンテンツ)。 リターンマップ。 } }
このクラスCallableTemplate上に継承し、我々は戻り値は地図で欲しいので、ジェネリック型がクラスで、地図では、プロセスアプローチ、ビジネス・ロジック・プロセスでメールを送信するために呼び出すSendMessageService.sendMessageインタフェース、およびリターンを上書きします私は、単純な処理、電子メールアドレスや地図のコンテンツを直接返す地図、に結果を返す。また、このクラスは、コンストラクタのパラメータは、ビルダーによって必要な受信パラメータで渡さする必要があることに注意
SendMessageTest.java、テストクラス
パッケージcom.gdut.thread.multiThread; 輸入はjava.util.ArrayList; 輸入はjava.util.List; 輸入java.util.Map; 輸入java.util.Map.Entry。 輸入java.util.concurrent.ExecutionException。 パブリック クラスSendMessageTest { 公共 静的 ボイドメイン(文字列[]引数)がスローInterruptedExceptionある、ExecutionException { ICallableTaskFrameWork callableTaskFrameWork = 新しいCallableTaskFrameWorkを(); 一覧 <CallableTemplate <地図<文字列、文字列>>>タスク= 新しいですArrayListの<CallableTemplate <地図<文字列、文字列>>> (); SendMessageHander sendMessageHander = ヌル; // セットで、電子メールアドレスと電子メールの内容が組み立てられている送信する必要がある ため(int型 I = 0;私は1000年の<; ++ I ){ sendMessageHander = 新しい新 sendMessageHander( "メールに" + I、 "コンテンツ" + I); tasks.add(sendMessageHander); } // 使い捨てマルチスレッドを通じて、メッセージを開始し、結果セットで取得する戻り リスト<地図<文字列、文字列>>結果= callableTaskFrameWork.submitsAll(手順); // 結果セットを返すの解析 のために(地図<文字列、文字列> 地図: 結果) {用(エントリ<文字列、文字列> エントリ:map.entrySet()){ System.out.printlnは(entry.getKey() + "\ tの" + entry.getValue())。 } } } }
業績
付録:あなたもここの記事を見ることができます: Javaは今だけ取得するには一つのインタフェースを必要とするライブオリジナルの10の同時非同期インタフェースをプログラミング!