0

Billing クラスには、Country wise Billing に関連するすべてのロジックがあります。データベースから結果を取得し、ユーザーに請求します。請求クラスは Runnable を実装します。膨大な数のユーザー (500 万以上) が非常に高速に請求されるように、国のパラメーターに従って請求を並行して実行したいと考えています。現在、完了するまでに何時間もかかります。

Billing クラスを実行するために ThreadPoolExecutor を実装しようとしていますが、その方法がわかりません。次の違いは何ですか、または私は何か間違ったことをしていますか? 提案してください!!全部で20カ国ありますが、ここに貼っているのは5カ国だけです。

 //for 20 countries  ThreadPoolExecutor (20,20,20.......)????

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS, 
new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());

executor.execute(new Billing("UK")); 
executor.execute(new Billing("USA")); 
executor.execute(new Billing("Germany")); 
executor.execute(new Billing("Spain")); 
executor.execute(new Billing("Italy")); 

また

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS, 
new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
for(int i=0;i<5;i++) // for 20 countries   i<20??
{    

   executor.execute(new Billing("UK")); 
   executor.execute(new Billing("USA")); 
   executor.execute(new Billing("Germany")); 
   executor.execute(new Billing("Spain")); 
   executor.execute(new Billing("Italy")); 
}

while (! executor.isTerminated()) {
   try{
      executor.awaitTermination(100, TimeUnit.SECONDS);
   }catch(InterruptedException iE)
   {
      iE.printStackTrace();
      System.out.println("Executor Exception: "+ iE);
   }

前もって感謝します!!

4

6 に答える 6

1

ループ ソリューションは正しくないようです。同じことを何度も実行する必要はありませんRunnable

と を に設定しThreadPoolExecutorて両方corePoolSizeでインスタンス化しています。つまり、エグゼキュータは、プール内のスレッドの数を、アイドル状態であっても に維持します。また、プールにはスレッドしか存在できないことも示しています。maximumPoolSize555

これにより、タスク (オブジェクト)5を並行して実行する最大のスレッドを期待できます。Billing

withメソッドにBillingオブジェクトを送信し続けると、指定した にオブジェクトが追加されます。このキューのサイズはこちらです。インスタンスによっては、キューがすでに最大容量に達しており、それ以上のタスクを処理できない場合があります。その場合、タスクは拒否され、コンストラクターで指定された に渡されます。その仕事は、実装されたメソッドで拒否されたタスクを処理することです。executorexecuteArrayBlockingQueue10RejectedExecutionHandlerThreadPoolExecutorrejectedExecution

拒否されたタスクがあるかどうかを確認したい場合はRejectedExecutionHandler、デフォルトを使用する代わりに、独自のタスクを提供する必要がありますThreadPoolExecutor.CallerRunsPolicy。次のようなものでそれを行うことができます:

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5,
        TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10),
        new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r,
                    ThreadPoolExecutor executor) {
                System.out.println("I got rejected: " + r);
                if (!executor.isShutdown()) {
                    r.run();
                }
            }
        });
于 2013-02-27T16:18:21.200 に答える
1

First: forget the loop

for(int i=0;i<5;i++) // for 20 countries   i<20??
{    

   executor.execute(new Billing("UK")); 
   executor.execute(new Billing("USA")); 
   executor.execute(new Billing("Germany")); 
   executor.execute(new Billing("Spain")); 
   executor.execute(new Billing("Italy")); 
}

this loops over all billings multiple times.

The right thing to do is in the first snippet:

executor.execute(new Billing("UK")); 
executor.execute(new Billing("USA")); 
executor.execute(new Billing("Germany")); 
executor.execute(new Billing("Spain")); 
executor.execute(new Billing("Italy")); 

Another error lies on the termination check:

while (! executor.isTerminated()) {
   try{
      executor.awaitTermination(100, TimeUnit.SECONDS);
   }catch(InterruptedException iE)
   {
      iE.printStackTrace();
      System.out.println("Executor Exception: "+ iE);
   }
}

The javadoc of Executor.awaitTermination says:

Blocks until all tasks have completed execution after a shutdown request,

but you never issue a shutdown request.

In your case, you could leverage the ExecutorCompletionService as in:

CompletionService<String> ecs = new ExecutorCompletionService<String>(executor);
List<String> countries= Arrays.asList("UK","USA","Germany","Spain","Italy");   
for(String country : countries) {
    ecs.submit(new Billing(country),country);
}
// wait for completion
for(int i=0;i<countries.size();i++){
      ecs.take(); // wait for next country completion
}
// all work completed, shutdown
executor.shutdownNow();
于 2013-02-27T16:41:29.770 に答える
0

コードのループ部分について話していると仮定するとfor、それがどのように機能するかは明らかではありません。

理想的には、ループは次のようになります。

for(String country : countryCollection) {
    executor.execute(new Billing(country));
}
于 2013-02-27T16:19:42.917 に答える
0

これを実装することを考える別の方法は、フォーク/結合フレームワークを調べることです。これは、仕事のスチールから本当に恩恵を受けることができるようです。たとえば、これを一見かなりきれいに分割できます。これにより、基本的に、国を代表しているように見えるスレッドがすべての請求を処理するのではなく、ユーザーまたはユーザーのサブセットによる請求のタスクを分割できます。

ライブラリへのリンクを見つけることができます:Javaのバージョン<7を使用している場合はここにあります

于 2013-02-27T16:42:52.040 に答える
0

ループの仕組みを理解しているかどうかわかりません。違いは、コードの 2 番目のブロックが、リストされている国ごとに 5 回請求を実行することです。

于 2013-02-27T16:17:34.307 に答える
0

の使用を検討しましたenumか?

static class Billing implements Runnable {

  enum Country {
    UK,
    USA,
    Germany,
    Spain,
    Italy;
  }

  public Billing(Country country) {
  }

  @Override
  public void run() {
  }
}
public void test() {
  ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS,
       new ArrayBlockingQueue<Runnable>(10), 
          new ThreadPoolExecutor.CallerRunsPolicy());
  for ( Billing.Country country : Billing.Country.values() ) {
    executor.execute(new Billing(country));
  }
}
于 2013-02-27T16:32:32.590 に答える