初识线程池

认识线程池

--|参考JDK API的理解:

线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法。每个 ThreadPoolExecutor 还维护着一些基本的统计数据,如完成的任务数。

--|其他理解:

--|减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

--|可以根据系统的承受能力,调整线程池中工作线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

--|假如创建线程的时间为t1,工作时间为t2,销毁时间为t3,当t1+t3>t2时,线程池的效率就更显而易见了。

Java5前后线程池

         --|Java5之前的线程池实现

了解Java5以前的线程池实现利于理解线程池的工作原理,而Java5以后的线程池都已经帮我们做好这些事情,我们只需要调用适合自己的线程池即可。

原理:创建指定数量的线程池,这些线程排队到列里面读取任务,若发现任务则执行,否则当前线程处于睡眠状态。新任务则不断往队列里面添加,有任务后则唤醒沉睡中的线程。

    --|Java5之后的线程池

        Executors.newFixedThreadPool(poolSize);

       固定大小的线程池。

       Executors.newSingleThreadExecutor();

单个后台线程。

       Executors.newCachedThreadPool();

无界线程池,可以进行自动线程回收。

       Executors.newScheduledThreadPool(poolSize);

指定线程数的线程池,可在指定延迟后执行线程任务.。poolSize是池中所保存的线程数,即使线程是空闲的也被保存在线程池内。

       Executors.newSingleThreadScheduledExecutor();

       单个后台线程,可进行自动回收线程。

--|其中前3个方法返回的是ExecutorService对象,后两个方法返回的是ScheduledExecutorService对象。ScheduledExecutorService是ExecutorService的子类,可以指定延迟后执行线程任务。

    --|Java7线程池

        待学习。

线程池类层次结构图

初识线程池
 

 

线程池工作原理图

初识线程池
 
 

 

代码示例:Java5前

package com.java5.before;

import java.util.LinkedList;

/**
 * java5前线程池
 * 
 * @fileName ThreadPool.java
 * @date 2013-4-25
 * @time 上午11:17:10
 * @author wst
 * 
 */
public class ThreadPool extends ThreadGroup {
	private boolean isClosed = false; // 线程池是否关闭
	private LinkedList<Runnable> workQueue; // 工作队列,具有先进先出特征
	private static int threadPoolID = 1; // 线程池的id

	/**
	 * 创建指定大小的线程池
	 * 
	 * @param poolSize
	 *            线程池中工作线程的数量
	 */
	public ThreadPool(int poolSize) {
		super(threadPoolID + ""); // 指定ThreadGroup的名称
		setDaemon(true); //标志为守护线程
		workQueue = new LinkedList<Runnable>(); // 初始化工作队列
		for (int i = 1; i <= poolSize; i++) {
			new WorkThread(i).start(); //启动线程池
		}
	}

	/**
	 * 向工作队列加入新任务,且通知空闲线程执行新任务
	 * 
	 * @date 2013-4-25
	 * @time 上午11:23:47
	 * @author wst
	 * @param task
	 * @return void
	 */
	public synchronized void addTaskForWorkQueue(Runnable task) {
		if (isClosed) {
			throw new IllegalStateException();
		}
		if (task != null) {
			workQueue.add(task);// 向队列中加入一个任务
			notify(); // 唤醒线程执行任务
		}
	}

	/**
	 * 从工作队列中取出一个任务,工作线程会调用此方法
	 * 
	 * @date 2013-4-25
	 * @time 上午11:26:58
	 * @author wst
	 * @param threadid
	 * @throws InterruptedException
	 * @return Runnable
	 */
	private synchronized Runnable getTask(int threadid)
			throws InterruptedException {
		while (workQueue.size() == 0) {
			if (isClosed) {
				return null;
			}
			System.out.println("工作线程" + threadid + "等待任务...");
			wait(); // 线程休息等待任务
		}
		System.out.println("工作线程" + threadid + "获取到任务...");
		return (Runnable) workQueue.removeFirst();
	}

	/**
	 * 关闭线程池
	 * @date 2013-4-25
	 * @time 上午11:30:41
	 * @author wst
	 * @return void
	 */
	public synchronized void closePool() {
		if (!isClosed) {
			waitFinish(); // 等待工作线程执行完毕
			isClosed = true;
			workQueue.clear(); // 清空工作队列
			interrupt(); // 中断线程池中的所有的工作线程
		}
	}

	/**
	 * 等待工作线程把所有任务执行完毕
	 * @date 2013-4-25
	 * @time 上午11:30:53
	 * @author wst
	 * @return void
	 */
	public void waitFinish() {
		synchronized (this) {
			isClosed = true;
			notifyAll(); // 唤醒所有还在getTask()方法中等待任务的工作线程
		}
		Thread[] threads = new Thread[activeCount()]; // activeCount()
		// 返回该线程组中活动线程的估计值
		int count = enumerate(threads); 
		for (int i = 0; i < count; i++) { // 等待所有工作线程结束
			try {
				threads[i].join(); // 等待工作线程结束
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		}
	}

	/**
	 * 内部类,工作线程,负责从工作队列中取出任务,并执行
	 * @fileName ThreadPool.java
	 * @date 2013-4-25
	 * @time 上午11:31:02
	 * @author wst
	 *
	 */
	private class WorkThread extends Thread {
		private int id;

		/**
		 * 取出指定id的任务
		 * @param id 任务id
		 */
		public WorkThread(int id) {
			// 父类构造方法,将线程加入到当前ThreadPool线程组中
			super(ThreadPool.this, id + "");
			this.id = id;
		}

		public void run() {
			while (!isInterrupted()) { // 判断线程是否被中断
				Runnable task = null;
				try {
					task = getTask(id); // 取出任务
				} catch (InterruptedException ex) {
					ex.printStackTrace();
				}
				if (task == null){
					return;
				}
				try {
					task.run();
				} catch (Throwable t) {
					t.printStackTrace();
				}
			}
		}
	}
}




package com.java5.before;


/**
 * java5前线程池,测试
 * 
 * @fileName ThreadPoolTest.java
 * @date 2013-4-25
 * @time 上午11:17:19
 * @author wst
 * 
 */
public class ThreadPoolTest {

	public static void main(String[] args) {
		//创建指定大小的线程池
		ThreadPool threadPool = new ThreadPool(3);
		try {
			// 休眠500毫秒,以便让线程池中的工作线程全部运行
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} 
		
		// 产生10个任务加入队列
		for (int i = 1; i <= 10; i++) {
			threadPool.addTaskForWorkQueue(createTask(i));
		}
		threadPool.waitFinish(); // 等待所有任务执行完毕
		threadPool.closePool(); // 关闭线程池

	}

	/**
	 * 产生一个具体任务
	 * @date 2013-4-26
	 * @time 下午01:24:00
	 * @author wst
	 * @param taskID
	 * @return Runnable
	 */
	private static Runnable createTask(final int taskID) {
		return new Runnable() {
			public void run() {
				System.out.println("Task" + taskID + "开始");
				System.out.println("Hello world");
				System.out.println("Task" + taskID + "结束");
				System.out.println();
			}
		};
	}
}

 

 

代码示例:Java5

package com.java5.after;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/***
 * java5以后线程池
 * 
 * @fileName ThreadPool.java
 * @date 2013-4-28
 * @time 下午01:25:44
 * @author wst
 * 
 */
public class ThreadPoolTest {

	/**
	 * @date 2013-4-28
	 * @time 下午01:25:33
	 * @author wst
	 * @param args
	 * @return void
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		ThreadPoolTest pool = new ThreadPoolTest();
		// pool.testFixedThreadPool(3,10);
		pool.testSingleThreadExecutor(10);
		// pool.testCachedThreadPool(10);
		// pool.testScheduledThreadPool(2,10,3000,TimeUnit.MILLISECONDS);
		// pool.testSingleThreadScheduledExecutor(10,3000,TimeUnit.MILLISECONDS);
		//BlockingQueue bqueue = new ArrayBlockingQueue(20); // 创建等待队列
		//pool.testUserDefinedThreadPool(10, 2, 5, 3000, TimeUnit.MILLISECONDS,bqueue);
	}

	/**
	 * 
	 * 固定数量线程池 
	 * 当要加入池的任务数量(taskCount)超过池最大尺寸(poolSize)时候 入此线程池则需要排队等待
	 * 线程池可重用
	 * 
	 * @date 2013-7-25
	 * @time 上午11:39:51
	 * @author wst
	 * @param poolSize
	 *            线程池大小
	 * @param taskCount
	 *            任务数量
	 * @return void
	 */
	private void testFixedThreadPool(int poolSize, int taskCount) {
		ExecutorService pool = Executors.newFixedThreadPool(poolSize);
		for (int i = 1; i <= taskCount; i++) {
			pool.execute(new MyThread(i));
		}
		pool.shutdown();// 关闭线程池
	}

	/**
	 * 单个后台线程
	 * 
	 * @date 2013-7-25
	 * @time 上午11:43:53
	 * @author wst
	 * @param taskCount
	 *            任务数量
	 * @return void
	 */
	private void testSingleThreadExecutor(int taskCount) {
		ExecutorService pool = Executors.newSingleThreadExecutor();
		for (int i = 1; i <= taskCount; i++) {
			pool.execute(new MyThread(i));
		}
		pool.shutdown();
	}

	/**
	 * 创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将被缓存在线程池中.
	 * 创建一个可根据需要创建新线程的线程池,
	 * 但是在以前构造的线程可用时将重用它们。
	 * 对于执行很多短期异步任务的程序而言,
	 * 这些线程池通常可提高程序性能。 
	 * 调用 execute 将重用以前构造的线程(如果线程可用)。
	 * 如果现有线程没有可用的,则创建一个新线程并添加到池中。
	 * 终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
	 * 因此,长时间保持空闲的线程池不会使用任何资源。
	 * 
	 * @date 2013-7-25
	 * @time 上午11:45:41
	 * @author wst
	 * @param taskCount
	 *            任务数量
	 * @return void
	 */
	private void testCachedThreadPool(int taskCount) {
		ExecutorService pool = Executors.newCachedThreadPool();
		for (int i = 1; i <= taskCount; i++) {
			pool.execute(new MyThread(i));
		}
		pool.shutdown();
	}

	/**
	 * 创建具有指定线程数的线程池,它可以在指定延迟后执行线程任务.
	 * poolSize是指池中所保存的线程数,即使线程是空闲的也被保存在线程池内.
	 * 
	 * @date 2013-7-25
	 * @time 上午11:53:17
	 * @author wst
	 * @param poolSize
	 * @param taskCount
	 * @param delay
	 *            延迟时间
	 * @param unit
	 *            时间单位
	 * @return void
	 */
	private void testScheduledThreadPool(int poolSize, int taskCount,
			long delay, TimeUnit unit) {
		ScheduledExecutorService pool = Executors.newScheduledThreadPool(poolSize);
		for (int i = 1; i <= taskCount; i++) {
			pool.execute((Runnable) pool.schedule(new MyThread(i), delay,unit));
		}
		pool.shutdown();
	}

	/**
	 * 单线程延迟线程池
	 * 
	 * @date 2013-7-25
	 * @time 下午12:30:43
	 * @author wst
	 * @param taskCount
	 * @param delay
	 * @param unit
	 * @return void
	 */
	private void testSingleThreadScheduledExecutor(int taskCount, long delay,
			TimeUnit unit) {
		ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();
		for (int i = 1; i <= taskCount; i++) {
			pool.execute((Runnable) pool.schedule(new MyThread(i), delay,unit));
		}
		pool.shutdown();
	}

	/**
	 * 自定义线程池
	 * 
	 * @date 2013-7-25
	 * @time 下午01:20:47
	 * @author wst
	 * @param taskCount
	 *            任务数量
	 * @param corePoolSize
	 *            核心线程数量
	 * @param maximumPoolSize
	 *            最大线程数量
	 * @param keepAliveTime
	 *            当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间
	 * @param unit
	 *            时间单位
	 * @param workQueue
	 *            队列
	 * @return void
	 */
	private void testUserDefinedThreadPool(int taskCount, int corePoolSize,
			int maximumPoolSize, long keepAliveTime, TimeUnit unit,
			BlockingQueue<Runnable> workQueue) {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(corePoolSize,
				maximumPoolSize, keepAliveTime, unit, workQueue);
		for (int i = 1; i <= taskCount; i++) {
			pool.execute(new MyThread(i));
		}
		pool.shutdown();
	}
}

 

package com.java5.after;

/**
 * 我java5以后线程池,测试
 * 
 * @fileName MyThread.java
 * @date 2013-4-28
 * @time 下午01:27:18
 * @author wst
 * 
 */
public class MyThread implements Runnable {
	private int i;
	public MyThread(int i){
		this.i=i;
	}
	public void run() {
		try {
			Thread.sleep(500);
			System.out.println("线程"+Thread.currentThread().getName() 
					+"正在执行 task="+i);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

 

 

参数解读

corePoolSize - 池中所保存的线程数,包括空闲线程。

maximumPoolSize - 池中允许的最大线程数。

keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。

unit - keepAliveTime 参数的时间单位。

workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute方法提交的 Runnable任务。 

其他

强烈建议程序员使用较为方便的 Executors 工厂方法 Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)、Executors.newFixedThreadPool(int)(固定大小线程池)和 Executors.newSingleThreadExecutor()(单个后台线程),它们均为大多数使用场景预定义了设置。更多请参考JDK API1.6。

 

 

 

你可能感兴趣的:(线程池)