4のJavaの並行処理シリーズ:カスタムスレッドプール拒否の方針

入門

ThreadPoolExcutorAは、JDKスレッドプールを内蔵していますが、スレッドプールを作成するときにも、私たちはしばしば作成する方法を使用します。学生のほとんど理解が知っているスレッドプールは、スレッドプールは、キャッシュ設計の典型的なプールです。JDK4つのタスクは、ポリシーを否定するが、時には我々は、実際のビジネスニーズを満たすことができないので、この場合には、我々は拒否されたタスクのスレッドプールに対処することを拒否するためのポリシーをカスタマイズする必要が付属しています。

  • スレッドプールは、政策導入否定しています
  • ポリシーを否定カスタマイズする方法

まず、導入されたスレッドプールの拒否ポリシーが来ます

JDKには、スレッドプールの拒否戦略に付属している次の4つのカテゴリがあります。

1、DiscardPolicy:サイレント破棄タスクは、任意の処理をせずに処理することができません。

public static class DiscardPolicy implements RejectedExecutionHandler {
	public DiscardPolicy() { }
	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
}

2は、DiscardOldestPolicy:キュー内で最も古いタスクを破棄し、再度、現在のジョブを提出しようとします。

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
	public DiscardOldestPolicy() { }
	
	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
	
}

3、AbortPolicy:直接スロー正常に動作しているシステムを防ぎ例外。

public static class AbortPolicy implements RejectedExecutionHandler {
	public AbortPolicy() { }

	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }

}

4は、CallerRunsPolicy:実行するタスクは現在、それほど本当に廃棄しないタスクを実行する、破棄されますが、スレッドのパフォーマンスはおそらく急激な減少を提出することで、タスクを実行するために呼び出したスレッドに分割されます

public static class CallerRunsPolicy implements RejectedExecutionHandler {
	public CallerRunsPolicy() { }

	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
}

私たちは、最初の3つの戦略は、元のタスクを破棄していることがわかります。しかし、いくつかのビジネスシナリオでは、我々は残忍なタスクを破棄することはできません。第四拒否した戦略は、スレッドプールのスレッドを開始することにより廃棄されたタスクに対処することですが、問題があっても、スレッドプールのアイドルが、それはタスクが破棄を実行しませんが、メインスレッドの待ち時間がタスクを実行するスレッドプールを呼び出すことですミッションの終了時まで。

第二に、導入されたスレッドプールの拒否ポリシーが来ます

スレッドプールの定義では、我々は次のように、インターフェイスを実装することを拒否するための統一されたポリシーがあることがわかります。

public interface RejectedExecutionHandler {
	 void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

私たちは、彼らのビジネスニーズに応じて、独自のビジネスシナリオに沿って処理戦略を定義することができます。私たちは、主流のフレームワークの一部を見ることができ、あなた自身の自己処理戦略を定義する方法です。

プール拒否ポリシーで1、ネッティースレッド

 private static final class NewThreadRunsPolicy implements RejectedExecutionHandler {
        NewThreadRunsPolicy() {
            super();
        }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
                final Thread t = new Thread(r, "Temporary task executor");
                t.start();
            } catch (Throwable e) {
                throw new RejectedExecutionException(
                        "Failed to start a new thread", e);
            }
        }
    }

ソースは、上から見ることができるNettyハンドリングのタスクが破棄されていない、そしてこのアイデアCallerRunsPolicy同様の利点。ただでNettyカスタム枠戦略は長いリソースが新しいの作成を続行することができますようとして、新しい仕事を通じて廃棄されたスレッドのタスクを完了することはありませんが、我々はスレッドでそれを見に来るが作成され、何の制約条件拒否処理のためのスレッド。

プール拒否ポリシーでは2、ダボスレッド

public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {

    protected static final Logger logger = LoggerFactory.getLogger(AbortPolicyWithReport.class);

    private final String threadName;

    private final URL url;

    private static volatile long lastPrintTime = 0;

    private static Semaphore guard = new Semaphore(1);

    public AbortPolicyWithReport(String threadName, URL url) {
        this.threadName = threadName;
        this.url = url;
    }

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        String msg = String.format("Thread pool is EXHAUSTED!" +
                        " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," +
                        " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!",
                threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), e.getLargestPoolSize(),
                e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(),
                url.getProtocol(), url.getIp(), url.getPort());
        logger.warn(msg);
        dumpJStack();
        throw new RejectedExecutionException(msg);
    }

    private void dumpJStack() {
       //省略实现
    }
}

Dubboカスタムログ出力現在のスレッドのスタック情報を印刷して、実行し、戦略を拒否しJDK、デフォルトポリシーを否定します。

88元記事公開 ウォン称賛49 ビューに10万+を

おすすめ

転載: blog.csdn.net/Diamond_Tao/article/details/100183424