多線程:線程池的拒絕策略

當線程池中的資源全部被佔用時,對於新添加的runnable有不同的處理策略,默認情況下有如下四種拒絕策略:
    RejectedExecutionHandler rejected = null;
    rejected = new ThreadPoolExecutor.AbortPolicy();//默認,隊列滿了丟任務拋出異常
    rejected = new ThreadPoolExecutor.DiscardPolicy();//隊列滿了丟任務不異常
    rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//將最早進入隊列的任務刪,之後再嘗試加入隊列
    rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到線程池失敗,那麼主線程會自己去執行該任務

參考文獻:https://www.cnblogs.com/muxi0407/p/11811669.html

 

1.AbortPolicy策略:當任務添加到線程池被拒絕時拋出異常(其中被拒絕分爲workQueue滿了或者調用shutdown()方法)該拒絕策略爲線程池的默認拒絕策略。

a.workQueue被用完 

package com.springboot.thread;

import java.util.concurrent.*;

public class AbortPolicyTest {

    public static void main(String[] args) {
        //ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
        LinkedBlockingQueue linked  = new LinkedBlockingQueue(2);
        //LinkedBlockingDeque linked  = new LinkedBlockingDeque(2);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked,new ThreadPoolExecutor.AbortPolicy());
        AbortPolicyRunnable runnable = new AbortPolicyRunnable();
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
    }
}

class AbortPolicyRunnable implements Runnable{
    @Override
    public void run() {
        try {
            //System.out.println("began : current thread is :"+ Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("end : current thread is :"+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運行結果:

Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.springboot.thread.AbortPolicyRunnable@58372a00 rejected from java.util.concurrent.ThreadPoolExecutor@4dd8dc3[Running, pool size = 3, active threads = 3, queued tasks = 2, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.springboot.thread.AbortPolicyTest.main(AbortPolicyTest.java:18)
end : current thread is :pool-1-thread-1
end : current thread is :pool-1-thread-3
end : current thread is :pool-1-thread-2
end : current thread is :pool-1-thread-1
end : current thread is :pool-1-thread-3

b.使用shutdown()方法

package com.springboot.thread;

import java.util.concurrent.*;

public class AbortPolicyTest {

    public static void main(String[] args) {
        //ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
        LinkedBlockingQueue linked  = new LinkedBlockingQueue(2);
        //LinkedBlockingDeque linked  = new LinkedBlockingDeque(2);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked,new ThreadPoolExecutor.AbortPolicy());
        AbortPolicyRunnable runnable = new AbortPolicyRunnable();
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.shutdown();
        threadPoolExecutor.execute(runnable);
        /*threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);*/
    }
}

class AbortPolicyRunnable implements Runnable{
    @Override
    public void run() {
        try {
            //System.out.println("began : current thread is :"+ Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("end : current thread is :"+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運行結果:

Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.springboot.thread.AbortPolicyRunnable@3b9a45b3 rejected from java.util.concurrent.ThreadPoolExecutor@7699a589[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.springboot.thread.AbortPolicyTest.main(AbortPolicyTest.java:15)
end : current thread is :pool-1-thread-1

c.從如下源碼代碼可以看出AbortPolicy爲線程的默認拒絕策略

private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();


public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

2.DiscardPolicy:當任務添加到線程池中被拒絕時,直接丟棄被拒接的任務,不拋出異常。

package com.springboot.thread;

import java.util.concurrent.*;

public class AbortPolicyTest {

    public static void main(String[] args) {
        //ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
        //LinkedBlockingQueue linked  = new LinkedBlockingQueue(2);
        //LinkedBlockingDeque linked  = new LinkedBlockingDeque(2);
        SynchronousQueue linked = new SynchronousQueue();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked,new ThreadPoolExecutor.DiscardPolicy());
        AbortPolicyRunnable runnable = new AbortPolicyRunnable();
        threadPoolExecutor.execute(runnable);
        //threadPoolExecutor.shutdown();
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
    }
}

class AbortPolicyRunnable implements Runnable{
    @Override
    public void run() {
        try {
            //System.out.println("began : current thread is :"+ Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("end : current thread is :"+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運行結果:

end : current thread is :pool-1-thread-2
end : current thread is :pool-1-thread-3
end : current thread is :pool-1-thread-1

3.DiscardOldestPolicy策略:當任務添加到線程池中被拒絕時,線程池會放棄等待隊列中最舊未處理的任務,然後將被拒絕的任務添加到等待隊列中。

(1).不使用SynchronousQueue

package com.springboot.thread;

import java.util.concurrent.*;

public class AbortPolicyTest {

    public static void main(String[] args) {
        //ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
        //LinkedBlockingQueue linked  = new LinkedBlockingQueue(2);
        LinkedBlockingDeque linked  = new LinkedBlockingDeque(2);
        //SynchronousQueue linked = new SynchronousQueue();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked,new ThreadPoolExecutor.DiscardOldestPolicy());
        AbortPolicyRunnable runnable = new AbortPolicyRunnable();
        threadPoolExecutor.execute(runnable);
        //threadPoolExecutor.shutdown();
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
    }
}

class AbortPolicyRunnable implements Runnable{
    @Override
    public void run() {
        try {
            //System.out.println("began : current thread is :"+ Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("end : current thread is :"+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 運行結果:

end : current thread is :pool-1-thread-3
end : current thread is :pool-1-thread-2
end : current thread is :pool-1-thread-1
end : current thread is :pool-1-thread-3
end : current thread is :pool-1-thread-2

(2).使用 SynchronousQueue

package com.springboot.thread;

import java.util.concurrent.*;

public class AbortPolicyTest {

    public static void main(String[] args) {
        //ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
        //LinkedBlockingQueue linked  = new LinkedBlockingQueue(2);
        //LinkedBlockingDeque linked  = new LinkedBlockingDeque(2);
        SynchronousQueue linked = new SynchronousQueue();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked,new ThreadPoolExecutor.DiscardOldestPolicy());
        AbortPolicyRunnable runnable = new AbortPolicyRunnable();
        threadPoolExecutor.execute(runnable);
        //threadPoolExecutor.shutdown();
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
    }
}

class AbortPolicyRunnable implements Runnable{
    @Override
    public void run() {
        try {
            //System.out.println("began : current thread is :"+ Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("end : current thread is :"+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運行結果:

Exception in thread "main" java.lang.StackOverflowError
	at java.util.concurrent.SynchronousQueue.offer(SynchronousQueue.java:912)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1361)
	at ......
end : current thread is :pool-1-thread-2
end : current thread is :pool-1-thread-3

 當使用同步無緩存隊列時,當我們的runnable大於線程池的的最大線程數並使用忽略最舊未執行任務時會報棧溢出的異常。

4.CallerRunsPolicy策略:

如下截圖來自於《java併發編程:核心方法與核心框架》

但是本人覺得書中的描述有錯誤,並不是調用線程池的Thread對象來處理被拒絕的任務,而是誰讓線程池去處理任務那麼被拒絕的任務就由誰來處理。就比如你的上司給你分配任務,你下面又有幾個小弟,但是隻負責分配任務並不做任務,他分配任務的時候給你說了句“把任務分給兄弟沒,如果兄弟們沒做不完的話把 多餘的任務給我做。”

package com.springboot.thread;

import java.util.concurrent.*;

public class AbortPolicyTest {

    public static void main(String[] args) {
        //ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
        //LinkedBlockingQueue linked  = new LinkedBlockingQueue(2);
        LinkedBlockingDeque linked  = new LinkedBlockingDeque(2);
        //SynchronousQueue linked = new SynchronousQueue();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked,new ThreadPoolExecutor.CallerRunsPolicy());
        AbortPolicyRunnable runnable = new AbortPolicyRunnable();
        threadPoolExecutor.execute(runnable);
        //threadPoolExecutor.shutdown();
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
    }
}

class AbortPolicyRunnable implements Runnable{
    @Override
    public void run() {
        try {
            //System.out.println("began : current thread is :"+ Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("end : current thread is :"+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運行結果:

end : current thread is :pool-1-thread-1
end : current thread is :main
end : current thread is :pool-1-thread-3
end : current thread is :pool-1-thread-2
end : current thread is :pool-1-thread-1
end : current thread is :pool-1-thread-3

從運行結果我們可以看到,main線程叫線程池去幹活,然後多餘的任務就自己幹了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章