线程池:3大方法、7大参数、4种拒绝策略
线程池的好处:
1、降低资源的消耗
2、提高响应的速度
3、方便管理。
线程复用、可以控制最大并发数、管理线程
public class ThreadPoolDemo {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor(); //单个线程
ExecutorService threadPool = Executors.newFixedThreadPool(5); //固定线程池大小
ExecutorService threadPool = Executors.newCachedThreadPool(); // 可伸缩,遇强则强
try {
for (int i = 0; i < 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "执行了");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
源码分析:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
// 都是调用的 ThreadPoolExecutor 函数
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
int maximumPoolSize, //最大核心线程池大小
long keepAliveTime, //超时时间
TimeUnit unit, //超时单位
BlockingQueue<Runnable> workQueue, //阻塞队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler) { //拒绝策略
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
ThreadPoolExecutor.AbortPolicy() // 队列满了之后就不处理,抛出异常
ThreadPoolExecutor.CallerRunsPolicy() // 哪里来去哪里
ThreadPoolExecutor.DiscardPolicy() //队列满了就丢弃任务
ThreadPoolExecutor.DiscardOldestPolicy() //队列满了就去和最早的竞争,不会抛出异常
最大的线程数应该如何设置?maximumPoolSize
// 获取CPU的核数
int processors = Runtime.getRuntime().availableProcessors();
新时代的程序员:lambda表达式、链式编程、函数式接口、Stream流式计算
public class FunctionDemo {
public static void main(String[] args) {
/*Function function = new Function() {
@Override
public String apply(String str) {
return str;
}
};*/
Function function = (str) -> {
return str;
};
System.out.println(function.apply("hello"));
}
}
public class PredicateDemo {
public static void main(String[] args) {
/*Predicate predicate = new Predicate() {
@Override
public boolean test(String str) {
return str.isEmpty();
}
};*/
Predicate<String> predicate = (str) -> {return str.isEmpty();};
System.out.println(predicate.test("hello"));
}
}
public class ConsumerDemo {
public static void main(String[] args) {
/*Consumer consumer = new Consumer() {
@Override
public void accept(String s) {
System.out.println("消费了" + s);
}
};*/
Consumer<String> consumer = (str) -> {
System.out.println("消费了" + str);
};
consumer.accept("美食");
}
}
public class SupplierDemo {
public static void main(String[] args) {
/*Supplier supplier = new Supplier() {
@Override
public Integer get() {
System.out.println("调用了get方法");
return 1024;
}
};*/
Supplier<Integer> supplier = () -> {return 1024;};
System.out.println(supplier.get());
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private Integer id;
private String name;
private Integer age;
}
/**
* 题目要求:一分钟内完成此题,只能用一行代码实现!
* 现在有5个用户!筛选:
* 1、ID 必须是偶数
* 2、年龄必须大于23岁
* 3、用户名转为大写字母
* 4、用户名字母倒着排序
* 5、只输出一个用户!
*/
public class StreamDemo {
public static void main(String[] args) {
User u1 = new User(1,"a",21);
User u2 = new User(2,"b",22);
User u3 = new User(3,"c",23);
User u4 = new User(4,"d",24);
User u5 = new User(6,"e",25);
// 集合就是存储
List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
// 计算交给Stream流
list.stream()
.filter(user -> user.getId()%2 == 0)
.filter(user -> user.getAge() > 23)
.map(user -> {
user.setName(user.getName().toUpperCase());
return user;
})
.sorted((user1, user2) -> {
return user2.getName().compareTo(user1.getName());
})
.limit(1)
.forEach(System.out::println); // User(id=6, name=E, age=25)
}
}
ForkJoin 在 JDK 1.7 , 并行执行任务!提高效率。大数据量!
ForkJoin 特点:工作窃取,每一个线程的任务都是一个双端队列,当一个线程完成任务之后,可以争抢别人的任务来执行。
public class ForkJoinDemo extends RecursiveTask<Long> {
private Long start;
private Long end;
private Long temp = 10000L; // 临界值
public ForkJoinDemo(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if ((end - start) < temp) {
Long sum = 0L;
for (Long i = start; i <= end; i++) {
sum += i;
}
return sum;
} else {
long middle = (start + end) / 2;
ForkJoinDemo task1 = new ForkJoinDemo(start, middle);
task1.fork();
ForkJoinDemo task2 = new ForkJoinDemo(middle, end);
task2.fork();
return task1.join() + task2.join();
}
}
}
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// test1(); //2033 ms
// test2(); //1229 ms
// test3(); //121 ms
}
// Stream并行流
public static void test3() {
long start = System.currentTimeMillis();
long sum = LongStream.rangeClosed(0L, 10000_0000L).parallel().reduce(0, Long::sum);
long end = System.currentTimeMillis();
System.out.println("sum="+"时间:"+(end-start));
}
// ForkJoin
public static void test2() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinDemo(0L, 10000_0000L);
ForkJoinTask<Long> submit = forkJoinPool.submit(task);
Long sum = submit.get();
long end = System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
//普通方法
public static void test1() {
Long sum = 0L;
long start = System.currentTimeMillis();
for (Long i = 1L; i <= 10000_0000; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
}
public class FutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 没有返回值的 runAsync 异步回调
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行了异步任务");
});
System.out.println("执行了main函数方法");
completableFuture.get(); //阻塞,获取执行结果
}
}
public class FutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 有返回值的 supplyAsync 异步回调
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + "执行了有返回值的异步回调");
int i = 1 / 0;
return 200;
});
System.out.println(completableFuture.whenComplete((t, u) -> {
System.out.println("t=" + t); // 返回正常结果
System.out.println("u=" + u); // 返回错误信息 u=java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
}).exceptionally((e) -> {
System.out.println(e.getMessage());
return 404; // 可以获得错误的返回结果
}).get()
);
}
}