1、FixedThreadPool
固定容量的线程池,线程池默认的容量上限是Integer.MAX_VALUE。常见的线程池容量:pc=200,服务器=1000~10000
FixedThreadPool一般由Executors(工具类)来获取,并可以指定线程池的容量。线程池是一个进程级的重量级资源。默认的生命周期和JVM一致。当开启线程池后,知道JVM关闭为止,是线程池的默认生命周期。可以通过调用shutdown方法来让线程池执行完所有的任务后,自动关闭。
Executor是线程池顶级接口,定义了execute(Runnable) 方法。调用的时候提供Runnable的实现,线程池通过这个线程去执行这个Runnable。
ExecutorService是Executro的子接口。
下面的代码定义了具有5个线程的线程池,初始化6个线程去运行任务,shutdown并不是马上关闭,是等到线程池中的任务执行结束后再关闭
package com.sunyou.p5;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/*
* 容量固定的线程池。活动状态和线程池容量是有上限的线程池。
* 所有的线程池中,都有一个任务队列。
* 使用的是 BlockingQueue<Runnable>作为任务的载体。
* 当任务数量大于线程池容量的时候,没有运行的任务保存在任务队列中,当线程有空闲的,自动从队列中取出任务执行
*
* 常见的线程池容量 pc-20 服务器 1000-10000
*/
public class FixedThreadPoolTest {
private static ExecutorService service = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws Exception {
for(int i = 0; i < 6; i++) {
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行");
}
});
}
System.out.println(service);//service如果不关,程序会一直运行
System.out.println(service.isShutdown());
System.out.println(service.isTerminated());
service.shutdown();
TimeUnit.SECONDS.sleep(2);
System.out.println(service);
System.out.println(service.isShutdown());
System.out.println(service.isTerminated());
}
}
运行结果
pool-1-thread-1正在执行
pool-1-thread-5正在执行
pool-1-thread-1正在执行
pool-1-thread-4正在执行
pool-1-thread-3正在执行
pool-1-thread-2正在执行
java.util.concurrent.ThreadPoolExecutor@42a57993[Running, pool size = 5, active threads = 1, queued tasks = 0, completed tasks = 5]
false
false
java.util.concurrent.ThreadPoolExecutor@42a57993[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 6]
true
true
2、Future
未来结果,代表线程任务执行结束后的结果。获取线程执行结果的方式是通过get方法获取。该方法会阻塞等待线程执行结束,并得到返回结果。如果该方法传入参数,阻塞固定时长,等待线程执行结束后的结果,如果等待过程中线程未执行结束会抛出异常。
package com.sunyou.p6;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class FutureTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService service = Executors.newFixedThreadPool(1);
Future<String> future = service.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("call method is start");
TimeUnit.SECONDS.sleep(1);
return Thread.currentThread().getName()+" is over";
}
});
System.out.println(future);
System.out.println(future.isDone());
System.out.println("future的返回值为 "+future.get());
System.out.println(future.isDone());
}
}
执行结果
java.util.concurrent.FutureTask@33909752
call method is start
false
future的返回值为 pool-1-thread-1 is over
true
3、使用FixedThreadPool来进行串行计算和并行计算时间
下列代码计算2000000以内的质数,并将其添加到list集合中。在并行过程中,将2000000这个数进行划分,划分为5各组。每个组开一个线程进行计算。最后比较二者的时间。
package com.sunyou.p6;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/*
* 使用FixedThreadPool来测试并行计算和串行计算效率
*/
public class ParallelComputingVSSerialComputing {
static class MyTask implements Callable<ArrayList<Integer>>{
int start,end;
MyTask(int start, int end){
this.start = start;
this.end = end;
}
@Override
public ArrayList<Integer> call() throws Exception {
ArrayList<Integer> list = new ArrayList<>();
boolean flag = true;
//找质数
for(int i = start; i <= end; i++) {
for(int j = 2; j <= Math.sqrt(i); j++) {
if(i % j == 0) {
flag = false;
break;
}
}
if(flag) {
list.add(i);
}
flag = true;
}
return list;
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
//串行计算
long start = System.currentTimeMillis();
serialComputing(1,2000000);
long end = System.currentTimeMillis();
System.out.println("Serial Computing time is " + (end - start) + " ms");
//多个task并行计算
ExecutorService service = Executors.newFixedThreadPool(5);
Future<ArrayList<Integer>> f1 = service.submit(new MyTask(1,60000));
Future<ArrayList<Integer>> f2 = service.submit(new MyTask(60001, 110000));
Future<ArrayList<Integer>> f3 = service.submit(new MyTask(110001, 150000));
Future<ArrayList<Integer>> f4 = service.submit(new MyTask(150001, 180000));
Future<ArrayList<Integer>> f5 = service.submit(new MyTask(180001, 200000));
start = System.currentTimeMillis();
f1.get();
f2.get();
f3.get();
f4.get();
f5.get();
end = System.currentTimeMillis();
System.out.println("Parallel Computing time is " + (end - start) + " ms");
}
public static void serialComputing(int start, int end) {
ArrayList<Integer> list = new ArrayList<>();
boolean flag = true;
//找质数
for(int i = start; i <= end; i++) {
for(int j = 2; j <= Math.sqrt(i); j++) {
if(i % j == 0) {
flag = false;
break;
}
}
if(flag) {
list.add(i);
}
flag = true;
}
}
}
执行结果
Serial Computing time is 1260 ms
Parallel Computing time is 20 ms
4、CachedThreadPool
缓存的线程池,容量不限(Integer.MAX_VALUE)。自动扩容,如果线程池中的线程数量不满足任务执行,创建新的线程。每次有新任务无法即时处理的时候都会创建新的线程。当线程池中的线程空闲时长达到一定临界值(默认60s),自动释放线程。
package com.sunyou.p6;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/*
* 缓存的线程池,容量不限(Integer.MAX_VALUE),自动扩容
* 如果线程池中的线程数量不满足任务执行,创建新的线程。每次执行新任务无法即时处理
* 的时候都会创建新的线程。
* 当线程池中的线程空闲时间超过一定临界值时(默认60s),自动释放线程。
*/
public class CachedThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
service.execute(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "- test");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
System.out.println(service);
// 默认线程空闲60s自动关闭
TimeUnit.SECONDS.sleep(70);
System.out.println(service);
}
}
执行结果
java.util.concurrent.ThreadPoolExecutor@75b84c92[Running, pool size = 5, active threads = 5, queued tasks = 0, completed tasks = 0]
pool-1-thread-3- test
pool-1-thread-1- test
pool-1-thread-4- test
pool-1-thread-2- test
pool-1-thread-5- test
java.util.concurrent.ThreadPoolExecutor@75b84c92[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 5]
5、SingleThreadExecutor
单一容量线程池。保证任务顺序执行。
package com.sunyou.p6;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/*
* 容量为1的线程池,保证任务顺序执行
*/
public class SingleThreadPoolTest {
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
for(int i = 0; i < 5; i++) {
service.execute(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "-test");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
执行结果
pool-1-thread-1-test
pool-1-thread-1-test
pool-1-thread-1-test
pool-1-thread-1-test
pool-1-thread-1-test
6、ScheduledThreadPool
计划任务线程池,可以根据计划自动执行任务的线程池。计划任务时使用。
package com.sunyou.p6;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/*
* 计划任务线程池
*/
public class ScheduledThreadPoolTest {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
System.out.println(service);
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-test");
}
//会一直执行
//第一次执行任务的时间 每次任务的时间间隔 时间间隔的单位
}, 0, 1, TimeUnit.SECONDS);
}
}
7、ForkJoinPool
分支合并线程池,适合处理复杂任务。线程池中运行的内容必须是ForkJoinTask的子类型(RecursiveTask、RecursiveAction)。task有返回结果,action无返回结果。
package com.sunyou.p6;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
/*
* 分支合并线程池,适合处理复杂任务
*/
public class ForkJoinPoolTest {
static int[] number = new int[1000000];
static final int MAX_VALUE = 50000;
static Random r = new Random();
//对数组初始化
static {
for(int i = 0; i < number.length; i++)
number[i] = r.nextInt(1000);
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
long start = System.currentTimeMillis();
long sum = 0;
for(int i = 0; i < number.length; i++)
sum += number[i];
long end = System.currentTimeMillis();
System.out.println("result is " + sum);
System.out.println("computing time is " + (end - start) + " ms");
start = System.currentTimeMillis();
ForkJoinPool pool = new ForkJoinPool();
Task task = new Task(0,1000000-1);
ForkJoinTask<Long> future = pool.submit(task);
sum = future.get();
end = System.currentTimeMillis();
System.out.println("result is " + sum);
System.out.println("computing time is " + (end - start) + " ms");
}
static class Task extends RecursiveTask<Long>{
int begin , end;
Task(int begin, int end){
this.begin = begin;
this.end = end;
}
@Override
protected Long compute() {
long sum = 0;
if((end - begin) < MAX_VALUE) {
for(int i = begin; i <= end; i++)
sum += number[i];
return sum;
}else {
int mid = begin + (end - begin) / 2;
Task task1 = new Task(begin, mid);
Task task2 = new Task(mid + 1, end);
//开启新的任务
task1.fork();
task2.fork();
//将结果合并返回
return task1.join() + task2.join();
}
}
}
}
result is 499490831
computing time is 10 ms
result is 499490831
computing time is 10 ms
8、ThreadPoolExecutor
线程池底层实现,除了ForkJoinPool外,其他常用的线程池都是使用ThreadPoolExecutor实现的。
package com.sunyou.p6;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/*
* 线程池底层实现
*/
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
//核心容量 最大容量 生命周期(0表示永久) 生命周期时间单位 任务队列
ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>());
for(int i = 0; i < 6; i++) {
pool.execute(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
System.out.println(pool);
System.out.println(pool.isTerminated());
System.out.println(pool.isShutdown());
pool.shutdown();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(pool);
System.out.println(pool.isTerminated());
System.out.println(pool.isShutdown());
}
}
结果
java.util.concurrent.ThreadPoolExecutor@42a57993[Running, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0]
false
false
pool-1-thread-2
pool-1-thread-4
pool-1-thread-1
pool-1-thread-5
pool-1-thread-3
pool-1-thread-2
java.util.concurrent.ThreadPoolExecutor@42a57993[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 6]
true
true