zoukankan      html  css  js  c++  java
  • java线程池

    线程池:

      简单理解,就是一个管理线程的池子。

    • 它帮我们管理线程,避免增加创建线程和销毁线程的资源消耗。因为线程其实也是一个对象,创建一个对象,需要经过类加载过程,销毁一个对象,需要走GC垃圾回收流程,都是需要资源开销的。
    • 提高响应速度。如果任务达到了,相对于从线程池拿线程,重新去创建一条线程执行,速度要慢很多。
    • 重复利用。线程使用完,再放回线程池,可以达到重复利用的效果,节省资源。

    线程池的创建:

      线程池可以通过ThreadpoolExecutor来创建:

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

      几个核心参数的作用:

    • corePoolSize:线程池核心线程数最大值
    • maximumPoolSize: 线程池最大线程数大小
    • keepAliveTime: 线程中非核心线程空闲的存活时间大小
    • unit: 线程空闲存活时间单位
    • workQueue:存放任务的阻塞队列
    • threadFactory:用于设置创建线程的工厂,可以给创建的线程设置有意义的名字,方便排查问题。
    • handler:线程池的饱和策略事件,主要有四种类型。

    任务执行:

    • 提交一个任务,线程池里存活的核心线程数小于线程数corePoolSize时,线程池会创建一个核心线程去处理提交的任务。
    • 如果线程核心线程数已满,线程数已经等于corePoolSize,一个新提交的任务,会被放进任务队列workQueue排队等待执行。
    • 当线程池里面已经存活的线程数已经等于corePoolSize,并且任务队列workQueue也满,判断线程数是否已满,如果没有,创建一个非核心线程执行提交的任务。、
    • 如果当前的线程数达到了maximumPoolSize,还有新的任务过来的话,直接采用拒绝策略处理。

    四种拒绝策略:

    • AbortPolicy(抛出一个异常,默认的)
    • DiscardPolicy(直接丢弃任务)
    • DiscaOldestPolicy(丢弃队列里最老的任务,将当前这个任务继续提交给线程池)
    • callerRunsPolicy(交给线程池调用所在的线程进行处理)

    线程池异常处理:

      在使用线程池处理任务的时候,任务代码可能抛出RuntimeException,抛出异常后,线程池可能捕获它,也可能创建一个新的线程来代替异常的线程,我们可能无法感知任务出现了异常,因此我们需要考虑线程池异常情况。

           ExecutorService executorService=Executors.newFixedThreadPool(6);
            for (int i = 0; i < 6; i++) {
                executorService.submit(()->{
                    System.out.println("current thread name"+Thread.currentThread().getName());
                    try {
                        Object object=null;
                        System.out.println("result"+object.toString());
                    }catch (Exception e){
                        System.out.println("program occur"+e);
                    }
                });
            }    

    看下源码:

        /**
         * @throws RejectedExecutionException {@inheritDoc}
         * @throws NullPointerException       {@inheritDoc}
         */
        public Future<?> submit(Runnable task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<Void> ftask = newTaskFor(task, null);
            execute(ftask);
            return ftask;
        }
    
        protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
            return new FutureTask<T>(runnable, value);
        }
    
        public FutureTask(Runnable runnable, V result) {
            this.callable = Executors.callable(runnable, result);
            this.state = NEW;       // ensure visibility of callable
        }
    
        public static <T> Callable<T> callable(Runnable task, T result) {
            if (task == null)
                throw new NullPointerException();
            return new RunnableAdapter<T>(task, result);
        } 
        public void execute(Runnable command) {
            if (command == null)
                throw new NullPointerException();
            int c = ctl.get();
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                    addWorker(null, false);
            }
            else if (!addWorker(command, false))
                reject(command);
        }
        public void run() {
            if (state != NEW ||
                !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                             null, Thread.currentThread()))
                return;
            try {
                Callable<V> c = callable;
                if (c != null && state == NEW) {
                    V result;
                    boolean ran;
                    try {
                        result = c.call();
                        ran = true;
                    } catch (Throwable ex) {
                        result = null;
                        ran = false;
                        setException(ex);
                    }
                    if (ran)
                        set(result);
                }
            } finally {
                // runner must be non-null until state is settled to
                // prevent concurrent calls to run()
                runner = null;
                // state must be re-read after nulling runner to prevent
                // leaked interrupts
                int s = state;
                if (s >= INTERRUPTING)
                    handlePossibleCancellationInterrupt(s);
            }
        }

    通过以上分析,submit执行的任务,可以通过Future对象的get()方法接收抛出的异常,再进行处理。因此可以通过future.get()来对异常进行处理。

        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(6);
            for (int i = 0; i < 6; i++) {
                Future future = executorService.submit(() -> {
                    System.out.println("current thread name" + Thread.currentThread().getName());
                    Object object = null;
                    System.out.println("result" + object.toString());
                });
                try {
                    future.get();
                } catch (Exception e) {
                    System.out.println("program occur" + e);
                }
            }
        }

    因此可以处理异常:

      1. 在任务代码try/catch进行异常捕获。

      2. 通过Future对象的get方法抛出异常,再进行捕获。

      3. 为工作者线程设置UncaughtExceptionHandler,在方法中处理异常。

        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(6, t -> {
                Thread thread = new Thread(t);
                thread.setUncaughtExceptionHandler((thread1, e) -> {
                    System.out.println(thread1.getName() + " occur:" + e);
                });
                return thread;
            });
            for (int i = 0; i < 8; i++) {
                executorService.execute(() -> {
                    Object object = null;
                    System.out.println("result" + object.toString());
                });
            }
        }
  • 相关阅读:
    day 011总结
    day 010 总结
    day 10作业
    day 009总结
    day 008总结
    wireshark 解密tls消息
    js基础 数组slice
    js基础 数组splice
    js基础 Array.from
    js基础 Array.of
  • 原文地址:https://www.cnblogs.com/award/p/11449567.html
Copyright © 2011-2022 走看看