美文网首页
Java并发编程(五) - 线程池(中)

Java并发编程(五) - 线程池(中)

作者: ElliotG | 来源:发表于2020-07-14 21:28 被阅读0次

    1. 拒绝策略

    超负荷了怎么办? 拒绝策略

    ThreadPoolExecutor最后一个参数指定了拒绝策略。
    也就是当任务数量超过了系统实际承载能力时,该如何处理。
    这个时候就要用到拒绝策略。
    拒绝策略通常用于系统超负荷运行时,也就是线程池中的线程已经用完了,无法继续为新任务服务,同时,
    等待队列中也已经满了,再也塞不下新任务了。

    JDK内置了四种拒绝策略:

    • AbortPolicy
      该策略会直接抛出异常,阻止系统正常工作。

    • CallerRunsPolicy
      只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。
      任务提交线程的性能有可能会急剧下降。

    • DiscardOldestPolicy
      该策略将丢弃最老的一个请求。

    • DiscardPolicy
      该策略默默地丢弃无法处理的任务。

    MyTask.java

    public class MyTask implements Runnable {
        @Override
        public void run() {
            System.out.println(System.currentTimeMillis() + ":Thread ID:" + Thread.currentThread().getId());
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    RejectThreadPoolDemo.java

    public class RejectThreadPoolDemo {
        public static void main(String[] args) throws InterruptedException {
            MyTask task = new MyTask();
            ExecutorService es = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingDeque<Runnable>(10),
                    Executors.defaultThreadFactory(),
                    new RejectedExecutionHandler() {
                        @Override
                        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                            System.out.println(r.toString() + " is discarded");
                        }
                    });
            for (int i=0;i<Integer.MAX_VALUE;i++) {
                es.submit(task);
                Thread.sleep(10);
            }
        }
    }
    

    上述代码定义了一个有5个常驻线程,并且最大线程数也是5个的线程池。
    这个线程池拥有一个10个容量的等待队列。
    而且,自定义了拒绝策略,将丢弃的任务信息进行打印。

     

    2. 自定义线程创建(ThreadFactory)

    线程池中的线程从哪里来?

    线程池是为了线程复用,避免线程的频繁创建。
    那么,最开始的那些线程从哪里来?
    答案是:
    ThreadFactory(线程工厂)

    ThreadFactory是一个接口,它只有一个方法newThread(Runnable r),用来创建线程。
    因此,我们需要实现它来自定义自己的线程工厂。

    通过自定义线程工厂来自定义线程创建有很多优势:

    • 跟踪线程池创建了多少线程
    • 自定义线程的名称,组以及优先级等信息
    • 将所有线程设置为守护线程

    示例代码:

    public class MyTask implements Runnable {
        @Override
        public void run() {
            System.out.println(System.currentTimeMillis() + ":Thread ID:" + Thread.currentThread().getId() + " Start...");
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println(System.currentTimeMillis() + ":Thread ID:" + Thread.currentThread().getId() + " End!");
        }
    }
    
    public class CustomThreadFactoryDemo1 {
        public static void main(String[] args) {
            int threadNum = 5;
    
            MyTask task = new MyTask();
    
            // 自定义线程工厂
            ExecutorService es = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
                    new SynchronousQueue<>(),
                    new ThreadFactory() {
                        @Override
                        public Thread newThread(@NotNull Runnable r) {
                            Thread t = new Thread(r);
                            t.setDaemon(true);
                            System.out.println("create " + t);
                            return t;
                        }
                    });
    
            for (int i = 0; i < threadNum; i++) {
                es.submit(task);
            }
    
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    运行结果:
    create Thread[Thread-0,5,main]
    create Thread[Thread-1,5,main]
    create Thread[Thread-2,5,main]
    create Thread[Thread-3,5,main]
    create Thread[Thread-4,5,main]
    1594989090932:Thread ID:14 Start...
    1594989090932:Thread ID:13 Start...
    1594989090933:Thread ID:16 Start...
    1594989090933:Thread ID:17 Start...
    1594989090932:Thread ID:15 Start...
    1594989091955:Thread ID:16 End!
    1594989091955:Thread ID:13 End!
    1594989091955:Thread ID:15 End!
    1594989091955:Thread ID:17 End!
    1594989091955:Thread ID:14 End!

    相关文章

      网友评论

          本文标题:Java并发编程(五) - 线程池(中)

          本文链接:https://www.haomeiwen.com/subject/nfyfhktx.html