线程池
普通创建线程方式的缺点:
"创建"线程和"销毁"线程都是比较占用内存和CPU的操作
对于一些数量多, 执行时间短的任务, 频繁的创建和销毁线程来执行, 会降低程序运行效率.
线程池:一个容纳多个线程的容器(集合)
线程池可以解决的问题:
其中的线程可以反复使用, 省去了频繁创建线程对象的操作, 无需反复创建线程而消耗过多资源
线程池的工作原理:提前创建好多个线程对象, 放在集合中. 多个任务来了反复使用这些线程对象来执行
线程池的创建和使用步骤:
1. 使用Executors的静态方法 newFixedThreadPool(int nThreads) 创建线程池ExecutorService
2. 创建一个任务类, 实现Runnable接口, 重写run()方法
3. 调用ExecutorService对象的 submit(Runnable task) 方法, 传递任务给线程池, 执行任务
4. 调用ExecutorService对象的 shutdown() 方法, 销毁线程池 (不建议执行)
单独创建的线程 和 线程池 的适用场景:
单独创建的线程: 适合任务执行时间长, 但数量少的场景 (包子铺吃货)
线程池: 适合任务执行时间短, 但数量多的场景 (网络请求, 10000个用户分别查看一个网页页面)
Lambda
函数式编程的好处:
简化代码编写 (使用 λ Lambda表达式, 简化匿名内部类的代码)
面向对象: 强调"用哪个对象的哪个方法"来做事 (注重语法形式: 继承 方法重写)
函数式: 强调"传入的参数 和 要执行的代码"
JDK 8 中, 加入的Lambda表达式, 是函数式编程思想中的重点 //如果版本是8以下的不可用
Lambda表达式的3个部分:
1. 一些参数 ()
接口中抽象方法的参数列表. 没参数就空着; 有参数就写, 多个参数用逗号分隔
2. 一个箭头 ->
将参数传递给方法体
3. 一段代码 {}
重写接口抽象方法的方法体
(数据类型 变量名, 数据类型 变量名) -> {
一些重写方法的代码
一些重写方法的代码
......
}
// 如果代码只有一行, 也可以合并写成一行
(参数列表) -> {一些重写方法的代码}
函数式接口:
函数式接口: "有且仅有一个抽象方法的接口"
但函数式接口对于 哪些方法算作抽象方法 有特殊规定:
1. 有方法体的方法"不算作"抽象方法, 如默认方法, 静态方法, 私有方法
2. 如果一个抽象方法 与 java.lang.Object类中的方法 定义相同的, 也"不算作"抽象方法
因为任何实现本接口的实现类, 都会直接或间接继承java.lang.Object类的public的方法, 所以 在创建实现类时其实不用重写该抽象方法, 也就不算作抽象方法
Lambda表达式的省略原则:
"可推导的都可省略" (凡是能根据前后代码能猜测出来的代码, 都可以省略不写)
1. (参数列表): 参数"类型"可以省略 (a, b) -> {}
2. (参数列表): 如果参数只有1个, 则"类型"和"小括号"都可以省略 a -> sout(a)
3. {一些代码}: 如果只有一条代码, 则"大括号", "return", "分号"都可以"一起省略"
Lambda表达式的使用前提:
1. Lambda只能用于接口, 且"接口中有且仅有一个抽象方法"(也称为"函数式接口")
普通类, 抽象类不能用
2. 使用Lambda必须具有上下文推断
接口中只能有一个抽象方法, 才能推断出来重写的是这个抽象方法
参数类型必须是函数式接口
|
|