java线程池详解

一、线程池的实现原理

提交一个任务到线程池中,线程池的处理流程如下:
1、判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。
2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
3、判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

二、线程池的创建

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,RejectedExecutionHandler handler)
corePoolSize:线程池核心线程数量
maximumPoolSize:线程池最大线程数量
keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
unit:存活时间的单位
workQueue:存放任务的队列
handler:超出线程范围和队列容量的任务的处理程序

三 、 RejectedExecutionHandler:饱和策略

当队列和线程池都满了,说明线程池处于饱和状态,那么必须对新提交的任务采用一种特殊的策略来进行处理。这个策略默认配置是AbortPolicy,表示无法处理新的任务而抛出异常。JAVA提供了4中策略:
1、AbortPolicy:直接抛出异常
2、CallerRunsPolicy:只用调用所在的线程运行任务
3、DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
4、DiscardPolicy:不处理,丢弃掉。

四 、设置策略有两种方式:

1、 RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS, queue,handler);
2、  ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS, queue);
  threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
五、个线程
package com.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolDemo {

	int i = 0;

	public static void main(String[] args) {
		ExecutorService singlePool = Executors.newSingleThreadExecutor();
		RunnableService runnableService = new RunnableService("张三" , 5000);
		// Thread t1=new Thread(runnableService);
		singlePool.execute(runnableService);

		ExecutorService fixedPool = Executors.newFixedThreadPool(2);
		ThreadService threadService = new ThreadService("lisi" , 2000);
		// Thread t2=new Thread(threadService);
		fixedPool.execute(threadService);
		fixedPool.execute(runnableService);
		System.out.println("线程执行完毕");

		ExecutorService cachePool = Executors.newCachedThreadPool();
		cachePool.execute(threadService);
		cachePool.execute(runnableService);
		

		ExecutorService schedualPool = Executors.newScheduledThreadPool(5);
		schedualPool.execute(threadService);
		schedualPool.execute(runnableService);
		
	}
}

测试线程

class ThreadService extends Thread {
	private String name;
	private int sleep_second;

	public ThreadService(String name , int sleep_second) {
		super();
		this.name = name;
		this.sleep_second = sleep_second;
	}

	@Override
	public void run() {
		try {
			Thread.sleep(sleep_second);
			System.out.println("ThreadService = " + name+"线程sleep了" + sleep_second/1000 + "s");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

测试线程2

class RunnableService implements Runnable {
	private String name;
	private int sleep_second;
	
	public RunnableService(String name , int sleep_second) {
		super();
		this.name = name;
		this.sleep_second = sleep_second;
	}

	@Override
	public void run() {
		try {
			Thread.sleep(2000);
			System.out.println("RunnableService = "+name+"线程sleep了" + sleep_second/1000 + "s");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

(1) newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程,线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
(2) newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。因为线程池大小为2,每个任务输出index后sleep 2秒,所以每两秒打印。定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
(3) newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。延迟执行
(4) newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

六、线程池的优点

1、线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。
2、可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。

你可能感兴趣的:(java)