多线程 - 线程池的实现

概述


系统启动一个新线程的成本是比较高的,因为它需要与系统交互,使用线程池可以有效地控制系统中并发线程的数量。尤其是当系统中需要创建大量生命周期很短的线程时,这种效果尤为明显。
线程池会在程序启动时创建一定数量的线程。当程序将一个Runnable对象或Callable对象传给线程池,线程池会启动一个线程来执行它的run()方法或call()方法。当run()方法或call()方法执行结束后,该线程不会立刻死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。

API


从Java 5以后,JDK新增了一个Executors工厂类来创建线程池,该工厂类包含如下几个静态方法:
  • newCachedThreadPool():创建一个具有缓冲功能的线程池,系统根据需要创建线程,这些线程将会被缓存在线程池中。
  • newFixedThreadPool(int nThreads):创建一个可重用、具有固定线程数的线程池。
  • newSingleThreadExecutor():创建一个只有一个线程的线程池。
  • newScheduledThreadPool(int corePoolSize):创建具有指定线程数的线程池,它可以在指定延迟后执行任务。corePoolSize指线程池中所保存的线程数,即使线程是空闲的也被保存在线程池内。
  • newSingleThreadScheduledExecutor():创建只有一个线程的线程池,它可以在指定延迟后执行任务。
前3个方法返回一个ExecutorService对象,它代表线程池,可以执行Runnable或Callable任务。后2个方法返回一个ScheduledExecutorService对象,它是ExecutorService的子类,在指定延迟后执行线程任务。ExecutorService提供了3个方法来执行线程任务:
  • Future<?> submit(Runnable task):将一个Runnable任务提交给线程池,线程池将在有空闲线程是执行Runnable任务。Future对象代表Runnable任务的返回值——run()方法没有返回值,将返回null。
  • <T> Future<T> submit(Runnable task, T result):将一个Runnable任务提交给线程池,线程池将在有空闲线程是执行Runnable任务。其中result表示返回值,线程执行结束后返回result。
  • <T> Future<T> submit(Callable<T> task):将一个Callable任务提交给线程池,线程池将在有空闲线程是执行Callable任务。Future对象代表Callable任务的返回值。
当执行完线程任务后,应该关闭线程池。调用shutdown()方法后,线程池将不再接收新的线程任务,并将所有正在执行的线程任务执行完毕后关闭线程池。shutdownNow()方法会停止所有正在执行的线程任务并关闭线程池。

代码示例


使用线程池来执行线程任务的步骤如下:
(1)调用Executors类的静态工厂方法创建一个ExecutorService对象,该对象代表一个线程池;
(2)创建Runnable实现类或Callable实现类的实例,作为线程任务;
(3)调用ExecutorService对象的submit()方法来提交线程任务;
(4)线程任务执行完毕后,关闭线程池。

package Demo;

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

class MyTask implements Runnable {
    @Override
    public void run() {
	for (int i = 0; i < 100; i++) {
	    System.out.println(Thread.currentThread().getName() + "的i值为" + i);
	}
    }
}

public class ThreadPoolDemo {

    public static void main(String[] args) {
	// 创建线程池,容量为4
	ExecutorService threadPool = Executors.newFixedThreadPool(4);
	// 提交三个线程任务
	threadPool.submit(new MyTask());
	threadPool.submit(new MyTask());
	threadPool.submit(new MyTask());
	// 关闭线程池
	threadPool.shutdown();
    }
}
测试结果:
pool-1-thread-1的i值为0
pool-1-thread-2的i值为0
pool-1-thread-2的i值为1
pool-1-thread-2的i值为2
pool-1-thread-3的i值为0
pool-1-thread-2的i值为3
pool-1-thread-1的i值为1
pool-1-thread-2的i值为4
pool-1-thread-2的i值为5
pool-1-thread-2的i值为6
pool-1-thread-3的i值为1
pool-1-thread-2的i值为7
pool-1-thread-2的i值为8
pool-1-thread-2的i值为9
pool-1-thread-2的i值为10
pool-1-thread-2的i值为11
pool-1-thread-2的i值为12
pool-1-thread-2的i值为13
......

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章