一、通过接口ExecutorService的实现类ThreadPoolExecutor创建
1.ThreadPoolExecutor构造器参数说明
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
参数一: corePoolSize: 指定线程池的核心线程的数量
参数二: maximumPoolSize: 指定线程池的最大线程数量。
参数三: keepAliveTime: 指定临时线程的存活时间。
参数四: unit: 指定临时线程存活的时间单位(秒、分、时、天)
参数五: workQueue: 指定线程池的任务队列。
参数六: threadFactory: 指定线程池的线程工厂。
参数七: handler: 指定线程池的任务拒绝策略(线程都在忙,任务队列也满了的时候,新任务来了该怎么处理)
2.ExecutorService的常用方法
方法名称 | 说明 |
---|---|
void execute(Runnable command) | 执行 Runnable 任务 |
Future<T> submit(Callable<T> task) | 执行 Callable 任务,返回未来任务对象,用于获取线程返回的结果 |
void shutdown() | 等全部任务执行完毕后,再关闭线程池 |
List<Runnable> shutdownNow() | 立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务 |
3.执行Runnable任务的Demo
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " => 执行任务");
try {
Thread.sleep(2000); //模拟任务执行了两秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
ExecutorService pool = new ThreadPoolExecutor(3,5,8, TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
Runnable target = new MyRunnable();
for (int i = 0; i < 9; i++) {
pool.execute(target);
}
}
}
4.执行Callable任务的Demo
public class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n) {
this.n = n;
}
@Override
public String call() throws Exception {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return Thread.currentThread().getName() + "计算1-" + n + "的和是:" + sum;
}
}
public class Test {
public static void main(String[] args) {
ExecutorService pool = new ThreadPoolExecutor(3,5,8, TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
Future<String> f1 = pool.submit(new MyCallable(100));
Future<String> f2 = pool.submit(new MyCallable(200));
Future<String> f3 = pool.submit(new MyCallable(300));
Future<String> f4 = pool.submit(new MyCallable(400));
try {
System.out.println(f1.get());
System.out.println(f2.get());
System.out.println(f3.get());
System.out.println(f4.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、通过线程池工具类Executors创建
1.常用方法
方法名称 | 说明 |
---|---|
public static ExecutorService newFixedThreadPool(int nThreads) | 创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程替代它。 |
public static ExecutorService newSingleThreadExecutor() | 创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。 |
public static ExecutorService newCachedThreadPool() | 线程数量随着任务增加而增加,如果线程任务执行完毕目空闲了60s则会被回收掉。 |
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) | 创建一个线程池,可以实现在给定的延迟后运行任务或者定期执行任务。 |
2.局限性
工具类Executors实际上还是通过ThreadPoolExecutor类实现,只是帮我们做了封装。这种方式不适合在大型并发系统里面使用,可能会出现系统风险。例如FixedThreadPool和SingleThreadPool在创建线程池的时候,允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致爆内存;CachedThreadPool允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而也会导致爆内存。
3.执行Runnable任务的Demo
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " => 执行任务");
try {
Thread.sleep(2000); //模拟任务执行了两秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
Runnable target = new MyRunnable();
for (int i = 0; i < 9; i++) {
pool.execute(target);
}
}
}
4.执行Callable任务的Demo
public class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n) {
this.n = n;
}
@Override
public String call() throws Exception {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return Thread.currentThread().getName() + "计算1-" + n + "的和是:" + sum;
}
}
public class Test {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
Future<String> f1 = pool.submit(new MyCallable(100));
Future<String> f2 = pool.submit(new MyCallable(200));
Future<String> f3 = pool.submit(new MyCallable(300));
Future<String> f4 = pool.submit(new MyCallable(400));
try {
System.out.println(f1.get());
System.out.println(f2.get());
System.out.println(f3.get());
System.out.println(f4.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}