多线程:线程池的拒绝策略

当线程池中的资源全部被占用时,对于新添加的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线程叫线程池去干活,然后多余的任务就自己干了。

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