Java 线程池的使用
1.自定义线程池构造器
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
2.线程池7大参数
**corePoolSize:**核心线程数(一直存在的线程)
**maximumPoolSize:**最大线程数,必须大于或等于核心线程数(临时线程数量=最大线程数-核心线程数)
keepAliveTime:临时线程最长空闲时间
**unit:**临时线程空闲时间单位,其静态单位见下表
微秒:TimeUnit.MICROSECONDS
秒:TimeUnit.SECONDS
分:TimeUnit.MINUTES
时:TimeUnit.HOURS
日:TimeUnit.DAYS
**workQueue:**任务队列---->此处是线程队列接口
实现类有:
1. new SynchronousQueue<>():没有容量,相当于占位符
2. new ArrayBlockingQueue<>(int capacity):数组实现的线程安全的有界的阻塞队列
3. new LinkedBlockingQueue(int capacity):以链表的方式实现的有界的阻塞队列,加了两把锁,
**threadFactory:**线程生成工厂(用于生成线程)
**handler:**拒绝策略
1. new ThreadPoolExecutor.AbortPolicy() 直接抛出异常
2. new ThreadPoolExecutor.CallerRunsPolicy() 调用当前线程池的所在的线程(主线程)去执行被拒绝的任务
3. new ThreadPoolExecutor.DiscardPolicy() 直接将异常的线程抛弃
4. new ThreadPoolExecutor.DiscardOldestPolicy() 当任务拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去
3.线程池相关方法
void shutdown() 执行完所有线程任务,关闭线程池
List<Runnable> shutdownNow() 立即关闭线程,并且返回未执行的线程
4.线程池验证demo
1.实现线程接口对象
package com.qq.demo;
/**
* @author 黔程似景
* @description 线程池使用demo
* @date 2022/1/9 16:18
**/
public class MyRunnable implements Runnable {
private final String name;
public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
Thread.currentThread().setName(name);
System.out.println(Thread.currentThread().getName() + "线程执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return name;
}
}
2.线程池实例(直接抛出异常)
package com.qq.pool;
import com.qq.demo.MyRunnable;
import java.util.concurrent.*;
/**
* @author 黔程似景
* @description 自定义线程池
* @date 2022/1/10 21:57
*
* workQueue:任务队列---->此处是线程队列接口,实现类有:
* new LinkedBlockingQueue(int capacity):以链表的方式实现的有界的阻塞队列,加了两把锁,
* handler:拒绝策略
* new ThreadPoolExecutor.AbortPolicy() 直接抛出异常
**/
public class MyThreadPoolRunnable {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(
1,
2,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
//核心线程执行
threadPool.execute(new MyRunnable("1" ));
//加入到任务队列
threadPool.execute(new MyRunnable("2" ));
//任务队列装满后,创建临时线程
threadPool.execute(new MyRunnable("3" ));
//抛出异常
threadPool.execute(new MyRunnable("4" ));
threadPool.execute(new MyRunnable("5"));
threadPool.execute(new MyRunnable("6"));
}
}
3.线程池实例(调用当前线程池的所在的线程(主线程)去执行被拒绝的任务)
package com.qq.pool;
import com.qq.demo.MyRunnable;
import java.util.concurrent.*;
/**
* @author 黔程似景
* @description 自定义线程池
* @date 2022/1/10 21:57
*
* workQueue:任务队列---->此处是线程队列接口,实现类有:
* new LinkedBlockingQueue(int capacity):以链表的方式实现的有界的阻塞队列,加了两把锁,
* handler:拒绝策略
* new ThreadPoolExecutor.CallerRunsPolicy() 调用当前线程池的所在的线程(主线程)去执行被拒绝的任务,此处是执行run方法,不是使用多线程
**/
public class MyThreadPoolRunnable {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(
1,
2,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
//核心线程执行
threadPool.execute(new MyRunnable("1" ));
//加入到任务队列
threadPool.execute(new MyRunnable("2" ));
//任务队列装满后,创建临时线程
threadPool.execute(new MyRunnable("3" ));
//抛出异常
threadPool.execute(new MyRunnable("4" ));
threadPool.execute(new MyRunnable("5"));
threadPool.execute(new MyRunnable("6"));
}
}
4.线程池实例(直接将异常的线程抛弃)
package com.qq.pool;
import com.qq.demo.MyRunnable;
import java.util.concurrent.*;
/**
* @author 黔程似景
* @description 自定义线程池
* @date 2022/1/10 21:57
*
* workQueue:任务队列---->此处是线程队列接口,实现类有:
* new LinkedBlockingQueue(int capacity):以链表的方式实现的有界的阻塞队列,加了两把锁,
* handler:拒绝策略
* new ThreadPoolExecutor.DiscardPolicy() 直接将异常的线程抛弃
**/
public class MyThreadPoolRunnable {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(
1,
2,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy());
//核心线程执行
threadPool.execute(new MyRunnable("1" ));
//加入到任务队列
threadPool.execute(new MyRunnable("2" ));
//任务队列装满后,创建临时线程
threadPool.execute(new MyRunnable("3" ));
//抛出异常
threadPool.execute(new MyRunnable("4" ));
threadPool.execute(new MyRunnable("5"));
threadPool.execute(new MyRunnable("6"));
}
}
5.线程池实例(会抛弃任务队列中最旧的任务,再把新任务添加进去)
package com.qq.pool;
import com.qq.demo.MyRunnable;
import java.util.concurrent.*;
/**
* @author 黔程似景
* @description 自定义线程池
* @date 2022/1/10 21:57
*
* workQueue:任务队列---->此处是线程队列接口,实现类有:
* new LinkedBlockingQueue(int capacity):以链表的方式实现的有界的阻塞队列,加了两把锁,
* handler:拒绝策略
* DiscardOldestPolicy() 当任务拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去
**/
public class MyThreadPoolRunnable {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(
1,
2,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
//核心线程执行
threadPool.execute(new MyRunnable("1" ));
//加入到任务队列
threadPool.execute(new MyRunnable("2" ));
//任务队列装满后,创建临时线程
threadPool.execute(new MyRunnable("3" ));
//抛出异常
threadPool.execute(new MyRunnable("4" ));
threadPool.execute(new MyRunnable("5"));
threadPool.execute(new MyRunnable("6"));
}
}
5.带返回值线程池
1.实现带返回值线程对象
package com.qq.demo;
import java.util.concurrent.Callable;
/**
* @author 黔程似景
* @description 带返回值的线程对象
* @date 2022/1/6 23:22
**/
public class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n) {
this.n = n;
}
public String call() throws Exception {
int count = 0;
for (int i = 1; i <= n; i++) {
count += i;
}
return Thread.currentThread().getName() + "统计1~" + n + "的和为:" + count;
}
}
2.线程池验证demo
package com.qq.pool;
import com.qq.demo.MyCallable;
import java.util.concurrent.*;
/**
* @author 黔程似景
* @description 线程池,支持带返回值多线程
* @date 2022/1/9 19:38
**/
public class ThreadPoolCallable {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
Future<String> future = threadPool.submit(new MyCallable(100));
Future<String> future1 = threadPool.submit(new MyCallable(200));
Future<String> future2 = threadPool.submit(new MyCallable(300));
Future<String> future3 = threadPool.submit(new MyCallable(400));
try {
String s = future.get();
System.out.println(s);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
try {
String s1 = future1.get();
System.out.println(s1);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
try {
String s2 = future2.get();
System.out.println(s2);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
try {
String s3 = future3.get();
System.out.println(s3);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}