今天看视频自学了java线程池,如果学习线程池的具体实现方法,在ExecutorService中有许多函数要重写,许多参数我也不太懂,所以我只是看了Executors类中三个工厂方法来创建线程池。
1.newSingleThreadExecutor
这个方法创建的线程池里只能同时运行一个线程,如果该线程在执行途中异常结束了,线程池会重新创建一个线程继续执行。
2.FixedThreadPool(int Threads)
这种线程池里可同时运行指定数量的线程,每完成了一个任务时就再创建一个线程去执行任务,直到线程数量达到线程池可同时运行的最大值,同singleThreadExecutor,如果有一个线程异常结束了,会自动创建一个线程补充其执行。
3.CachedThreadPool
这种线程池也是在完成一个任务后再创建一个线程,但不同于fixedThreadPool的是它没有限制数量,它里面所能容纳的最大线程数量理论上是依据计算机内存的大小而定的。另外,当线程池大小超过需要运行的线程时,线程池就会回收空闲的线程。而任务增加时又将智能的添加新线程来执行任务。
在JDK帮助文档中,有如此一段话:“强烈建议程序员使用较为方便的Executors工厂方法Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)、Executors.newFixedThreadPool(int)(固定大小线程池)和Executors.newSingleThreadExecutor()(单个后台线程)。它们均为大多数使用场景预定义了设置。”
我测试了三种线程池,代码如下:
class MyThread extends Thread {
int i = 0;
// 定义其中的run方法,方法是打印某线程在执行
public void run() {
while (i++ < 3)
System.out.println(this.getName() + "正在被执行。。。。。");
}
}
// 定义一个类,主要是为了让线程池执行里面的executeMethod方法。
public class ThreadPool {
//定义一个执行方法,形参接受一个线程池
public static void executeMethod(ExecutorService es) {
//让该线程池添加10个MyThread线程并执行。
for (int x : new int[5]) {
es.execute(new MyThread());
}
}
}
class SingleThread {
public static void main(String[] args) {
//定义一个单线程的线程池
ExecutorService singleThread = Executors.newSingleThreadExecutor();
//提示这是执行哪个线程池
System.out.println("这是执行singleThreadPool的结果:");
//让它执行ThreadPool类中定义的执行方法。
ThreadPool.executeMethod(singleThread);
//执行完就关闭该线程池
singleThread.shutdown();
//在打印的结果中我们可以看到,它是按顺序执行的,意味着它每次都只能同时运行一个任务。
}
}
class FixedThread {
public static void main(String[] args) {
//同上
ExecutorService fixedThread = Executors.newFixedThreadPool(3);
System.out.println("这是执行FixedThreadPool的结果:");
ThreadPool.executeMethod(fixedThread);
fixedThread.shutdown();
//在打印的结果中,我们可以看到,
//它在执行第一个任务后不断地创建新线程去执行余下的任务,直到线程数量达到了可允许的最大值。
//观察结果可发现,它同时执行的线程不超过3个。
}
}
class CachedThread {
public static void main(String[] args) {
//同上
ExecutorService cachedThread = Executors.newCachedThreadPool();
System.out.println("这是执行CachedThreadPool的结果:");
ThreadPool.executeMethod(cachedThread);
cachedThread.shutdown();
//在打印 的结果中,我们可以发现可缓存的线程池几乎可以同时运行所有线程。
}
}