美文网首页
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