java线程池
Posted award
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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()); );
以上是关于java线程池的主要内容,如果未能解决你的问题,请参考以下文章