• java 线程知识问答


    简介

    一个线程的核心线程数是4, 最大线程数是8, 有一个任务提交过来, 迅速执行王弼, 如果再来一个任务, 那么线程池是新建一个线程去执行还是会复用之前的线程?

    参考链接

    https://blog.csdn.net/hu10131013/article/details/105665232 (逻辑图片清晰)
    https://www.cnblogs.com/jxxblogs/p/11655670.html (测试代码来源)

    answer

    根据线程创建的逻辑而言.

    如果没有创建了4个核心线程, 会创建一个新线程来执行. 虽然第一个线程使用完毕了.

    测试代码

    import com.sun.xml.internal.ws.util.StringUtils;
    
    import java.io.Console;
    import java.util.concurrent.*;
    
    /**
     * Created by lee on 2021/6/28.
     */
    public class ThreadPoolLocal {
        public static void main(String[] args) throws InterruptedException {
            int size = 5;
            ThreadPoolExecutor es1 = new ThreadPoolExecutor(
                    4, // corePoolSize
                    8, // int maximumPoolSize
                    1,// long keepAliveTime
                    TimeUnit.DAYS, //   TimeUnit unit
                    new LinkedBlockingQueue<>(10) // BlockingQueue<Runnable> workQueue
            );
            for(int i=0; i<size; i++){
                es1.execute(new DemoTask(i));
    
                System.out.println("poolSize: " + es1.getPoolSize());
                System.out.println("corePoolSize: " + es1.getCorePoolSize());
                System.out.println("maximumPoolSize:" + es1.getMaximumPoolSize());
                System.out.println("queue:" + es1.getQueue().size());
                System.out.println("completedTaskCount:" + es1.getCompletedTaskCount());
                System.out.println("largestPoolSize:" + es1.getLargestPoolSize());
                System.out.println("keepAliveTime:" + es1.getKeepAliveTime(TimeUnit.SECONDS));
                Thread.sleep(3000); // 沉睡3s在执行下一个任务. 上一个任务2s就执行完毕了, 但是因为没有达到核心线程数, 还是去创建了新的线程.
    
            }
            es1.shutdown();
        }
    }
    
    class DemoTask implements Runnable {
        private int taskNum;
        public DemoTask(int taskNum) {
            this.taskNum = taskNum;
        }
    
        @Override
        public void run() {
            System.out.println("正在执行" + taskNum);
            try {
                Thread.sleep(2000);
            }catch(InterruptedException ex) {
                ex.printStackTrace();
            }
            System.out.println("执行完毕" + taskNum);
        }
    }
    
    

    线程池和核心参数和拒绝策略有哪些?

    线程池的构造函数有一些是默认的. 比如测试代码中使用的就是有部分默认的
    完整的应该是如下

    
        /**
         * Creates a new {@code ThreadPoolExecutor} with the given initial
         * parameters and default thread factory.
         *
         * @param corePoolSize the number of threads to keep in the pool, even
         *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
         * @param maximumPoolSize the maximum number of threads to allow in the
         *        pool
         * @param keepAliveTime when the number of threads is greater than
         *        the core, this is the maximum time that excess idle threads
         *        will wait for new tasks before terminating.
         * @param unit the time unit for the {@code keepAliveTime} argument
         * @param workQueue the queue to use for holding tasks before they are
         *        executed.  This queue will hold only the {@code Runnable}
         *        tasks submitted by the {@code execute} method.
         * @param handler the handler to use when execution is blocked
         *        because the thread bounds and queue capacities are reached
         * @throws IllegalArgumentException if one of the following holds:<br>
         *         {@code corePoolSize < 0}<br>
         *         {@code keepAliveTime < 0}<br>
         *         {@code maximumPoolSize <= 0}<br>
         *         {@code maximumPoolSize < corePoolSize}
         * @throws NullPointerException if {@code workQueue}
         *         or {@code handler} is null
         */
        public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  RejectedExecutionHandler handler) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), handler);
        }
    
         * @param handler the handler to use when execution is blocked
         *        because the thread bounds and queue capacities are reached // 当阻塞队列已经满了的时候, 我们应该使用哪些拒绝策略
    

    handler 就是拒绝策略, 简单来说.
    默认是会抛出异常, 将demo代码中的size 改成 100 可以看到抛出了一个异常.

    1、AbortPolicy:直接抛出异常。
    2、CallerRunsPolicy:只用调用者所在线程来运行任务。 -- 简单来说, 就是上述demo的main线程来运行任务.
    3、DiscardOldestPolicy:丢弃队列里最老(引用文献使用最近,感觉有问题)的一个任务,并执行当前任务。
    4、DiscardPolicy:不处理,丢弃掉。

    简单理解:
    如果很线程任务涌入的话, 直接奔溃报错.
    主线程分配了任务, 我线程池接受不了, 拒绝, 你自己做吧.
    新来的任务最重要, 旧的任务我就不做了.
    直接丢弃. 不做了.

    Hope is a good thing,maybe the best of things,and no good thing ever dies.----------- Andy Dufresne
  • 相关阅读:
    将文件夹压缩为jar包——JAVA小工具
    android json解析及简单例子(转载)
    Eclipse RCP中获取Plugin/Bundle中文件资源的绝对路径(转载)
    右键菜单的过滤和启动(转载)
    eclipse rcp应用程序重启
    使用PrefUtil设置全局配置
    模拟器屏幕大小
    Android实现下载图片并保存到SD卡中
    PhoneGap与Jquery Mobile组合开发android应用的配置
    android WebView结合jQuery mobile之基础:整合篇
  • 原文地址:https://www.cnblogs.com/eat-too-much/p/14944356.html
Copyright © 2020-2023  润新知