创建线程池:3大方法、7大参数、4 种拒绝策略
。
Executors
创建线程池:里面有三大方法
ThreadPoolExecutor
创建线程池:七大参数
、 四种拒绝策略
池化技术:
线程池的好处:
线程复用、可以控制最大并发数、管理线程
Executors工具类中提供了创建线程池的三大方法
,如果打开源码进行查看会发现,它们内部使用的使用的还是ThreadPoolExecutor来创建的线程池,就好比使用ThreadPoolExecutor创建线程池的阉割版
一样因此不建议使用
下面来看看这三个创建线程池的方法
的源码:
Executors.newSingleThreadExecutor()
:创建单个线程public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
Executors.newFixedThreadPool(5)
:创建一个固定的线程池大小 public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
Executors.newCachedThreadPool()
:可伸缩的线程池public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
线程池
不允许使用Executors去创建
,而是通过ThreadPoolExecutor的方式去创建,这样写让其他人更加明确线程的运行规则,规避资源耗尽的风险
Executors【返回线程池】的弊端如下:
FixedThreadPool
和SingleThreadPool
允许的请求对列长度为Integer.MAX_VALUE
,可能会堆积大量的请求造成OOM
CachedThreadPool
和CheduledThreadPool
允许创建的线程数量为Integer.MAX_VALUE
,可能会创建大量的线程造成OOM演示代码:
public class ThreadPoolTest01 {
public static void main(String[] args) {
ExecutorService threadPool01=Executors.newSingleThreadExecutor();//单个线程
ExecutorService threadPool02=Executors.newFixedThreadPool(5);//创建一个固定的线程池大小
ExecutorService threadPool03=Executors.newScheduledThreadPool(2);
ExecutorService threadPool04=Executors.newCachedThreadPool();//可伸缩的
try {
for(int i=0;i<10;i++){
//在此处修改使用哪个方法创建的线程池
threadPool01.execute(()->{
System.out.println(Thread.currentThread().getName()+" OK!!!");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();//线程池使用完需要关闭
}
}
}
七大参数:
使用这个来创建线程池
):构造方法里面有七个参数 public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
int maximumPoolSize,//最大核心线程池大小
long keepAliveTime,//没人调用时的存活时间,过期自动释放
TimeUnit unit,//超时单位
BlockingQueue<Runnable> workQueue,//阻塞对列
ThreadFactory threadFactory, //创建工厂,用来创建线程,一般不动
RejectedExecutionHandler defaultHandler)//【拒绝策略】
{
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, defaultHandler);
}
四种拒绝策略:
RejectedExecutionHandler
接口的四个实现类,也是ThreadPoolExecutor类
中的内部子类(使用默认的拒绝策略即可)默认拒绝策略:AbortPolicy()
不同拒绝策略的区别:
new ThreadPoolExecutor.AbortPolicy()
:队列满了,在创建线程,不处理这个创建过程的,抛出异常最大承载线程个数:最大核心线程池+阻塞对列
new ThreadPoolExecutor.CallerRunsPolicy()
:哪来的去哪里new ThreadPoolExecutor.DiscardPolicy()
:队列满了,丢掉任务,不会抛出异常new ThreadPoolExecutor.DiscardOldestPolicy()
:队列满了,尝试去和最早的竞争,也不会抛出异常!代码演示
public class ThreadPoolTest01 {
public static void main(String[] args) {
ExecutorService threadPool=new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try {
//最大承载:Deque+max-->3+5,超出会报异常
//触发max的条件:corePoolSize+Deque>max
for(int i=0;i<10;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" OK!!!");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();//线程池使用完需要关闭
}
}
}
ThreadPoolExecutor
并行
执行多少条线程):几核,就是几,可以保持CPU的效率最高代码演示:
public class Demo02 {
public static void main(String[] args) {
// 获取CPU的核数
System.out.println(Runtime.getRuntime().availableProcessors());
//创建线程池
ExecutorService threadPool=new ThreadPoolExecutor(2,
3,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());//AbortPolicy是一个内部类
try {
for(int i=0;i<6;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" OK!!!");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
新时代的程序员要掌握的技能:
函数式接口: 只有一个方法的接口
四大函数式接口:java.util.function
包下的四个原生的接口
@FunctionalInterface
public interface Function<T, R> { .....}
代码示例:
public class FunctionDemo1 {
public static void main(String[] args) {
//工具类:输出输入的值
//普通使用方法
Function function01= new Function<String,String>() {
@Override
public String apply(String string) {
return string;
}
};
System.out.println(function01.apply("aismall"));
//使用Lambda表达式
Function<String,String> function02=(str)->{return str;};
System.out.println(function02.apply("aismall"));
}
}
@FunctionalInterface
public interface Predicate<T> {.....}
代码示例:
public class PredicateDemo2 {
public static void main(String[] args) {
//工具类:判断字符串是否为空,为空返回true
Predicate predicate01= new Predicate<String>(){
@Override
public boolean test(String s) {
return s.isEmpty();
}
};
System.out.println(predicate01.test(""));
Predicate<String> predicate02=(str)->{return str.isEmpty();};
System.out.println(predicate02.test("aismall"));
}
}
@FunctionalInterface
public interface Consumer<T> {......}
代码演示:
public class ConsumerDemo3 {
public static void main(String[] args) {
Consumer<Integer> consumer01=new Consumer<Integer>() {
@Override
public void accept(Integer num) {
int a=num+666;
System.out.println(a);
}
};
consumer01.accept(100);
Consumer<Integer> consumer02=(num)->{
int a=num+666;
System.out.println(a);
};
consumer02.accept(100);//没有输出结果
}
}
@FunctionalInterface
public interface Supplier<T> {.....}
代码演示:
public class SupplierDemo4 {
public static void main(String[] args) {
Supplier<Test> supplier01=new Supplier<Test>() {
@Override
public Test get() {
Test test01 =new Test();
return test01;
}
};
Test test01=supplier01.get();
test01.show();
Supplier<Test> supplier02=()->{
Test test02 =new Test();
return test02;
};
Test test02=supplier02.get();
test02.show();
}
}
class Test{
public void show(){
System.out.println("Supplier接口测试。。。");
}
}
流式计算:类似于水流一样,然后我们对水进行处理,一级一级的进行过滤
代码演示:
public class User {
//有参,无参,get,set,toString
private int id;
private String name;
private int age;
}
public class Test {
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);
//创建一个集合存储这些User
List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
// 计算交给Stream流
// lambda表达式、链式编程、函数式接口、Stream流式计算
list.stream()
//找出id是偶数的
.filter(u->{return u.getId()%2==0;})
//年龄大于23
.filter(u->{return u.getAge()>23;})
//将名字转换为大写
.map(u->{return u.getName().toUpperCase();})
//只要第一个
.limit(1)
//打印输出
.forEach(System.out::println);
}
}