池化技术:减小每次获取资源的消耗,提升对资源的利用率。
线程池提供了一种限制和管理资源(包括执行一个任务)。 每一个线程池还维护一些基本统计信息,例如已完成任务的数量。编程
使用线程池的好处:数组
public void execute(Runnable command) { // 若是任务为null,则抛出异常。 if (command == null) throw new NullPointerException(); // ctl 中保存的线程池当前的一些状态信息 AtomicInteger int c = ctl.get(); //判断当前线程池中执行的任务数量是否小于corePoolSize if (workerCountOf(c) < corePoolSize) { //若是小于,则经过addWorker新建一个线程,而后,启动该线程从而执行任务。 if (addWorker(command, true)) return; c = ctl.get(); } //经过 isRunning 方法判断线程池状态 //线程池处于 RUNNING 状态才会被而且队列能够加入任务 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); // 再次获取线程池状态,若是线程池状态不是 RUNNING 状态就须要从任务队列中移除任务。 // 并尝试判断线程是否所有执行完毕。同时执行拒绝策略。 if (! isRunning(recheck) && remove(command)) reject(command); // 若是当前线程池为空就新建立一个线程并执行。 else if (workerCountOf(recheck) == 0) addWorker(null, false); } //经过addWorker新建一个线程,并将任务(command)添加到该线程中; //而后,启动该线程从而执行任务。 //若是addWorker执行失败,则经过reject()执行相应的拒绝策略的内容。 else if (!addWorker(command, false)) reject(command); }
线程池建立线程的时候,会将线程封装成工做线程Worker,Worker在执行完成任务以后,还会循环获取工做队列利的任务来执行。
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) {//循环执行任务 w.lock(); //若是线程池正在中止,确保线程被中断 if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } }
如何使用线程池?并发
ThreadPoolExecutor方法的构造参数有不少,咱们看看最长的那个就能够了:框架
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ? null : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
public class ThreadPoolTest { private static final int CORE_POOL_SIZE = 5; //核心线程数 private static final int MAX_POOL_SIZE = 10; //最大线程数 private static final int QUEUE_CAPACITY = 100; //任务队列的容量 private static final Long KEEP_ALIVE_TIME = 1L; //等待时间 public static void main(String[] args) { ThreadPoolExecutor threadPool = new ThreadPoolExecutor( CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<>(QUEUE_CAPACITY), new ThreadPoolExecutor.AbortPolicy()); for(int i = 0; i < 10 ; i ++){ Runnable worker = new MyRunnable(""+ i); //建立任务 threadPool.execute(worker); //经过execute提交 } threadPool.shutdown(); while(!threadPool.isTerminated()){ } System.out.println("Finished all threads"); }}class MyRunnable implements Runnable { private String command; MyRunnable(String s) { this.command = s; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " Start. Time = " + new Date()); processCommand(); System.out.println(Thread.currentThread().getName() + " End. Time = " + new Date()); } private void processCommand() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public String toString() { return this.command; }}
固然,也能够根据须要自定义拒绝策略,须要实现RejectedExecutionHandler。ide
1、使用ThreadPoolExecutor的各类构造方法。工具
2、经过Executor框架的工具类Executors能够建立三种类型的ThreadPoolExecutor。性能
《阿里巴巴 Java 开发手册》中强制线程池不容许使用 Executors 去建立,而是经过 ThreadPoolExecutor 的方式,这样的处理方式让写的同窗更加明确线程池的运行规则,规避资源耗尽的风险this
Executors 返回线程池对象的弊端以下: FixedThreadPool 和 SingleThreadExecutor: 容许请求的队列长度为 Integer.MAX_VALUE ,可能堆积大量的请求,从而致使 OOM。 CachedThreadPool 和 ScheduledThreadPool : 容许建立的线程数量为 Integer.MAX_VALUE ,可能会建立大量线程,从而致使 OOM。
threadPool.execute(new Runnable() { @Override public void run() { }}); //经过execute提交
Future<Object> future = threadPool.submit(hasReturnValueTask); try{ Object s = future.get(); }catch(InterruptedException e){ //处理中断异常 }catch(ExecutionException e){ //处理没法执行任务异常 }finally{ threadPool.shutdown(); }
若是以为本文对你有帮助,能够点赞关注支持一下spa