本帖最后由 谁用了我的名字 于 2018-9-21 21:14 编辑
就业班JavaSE第二阶段第7天
day07【线程池、Lambda表达式】
--等待与唤醒案例
线程间通信:
概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不同
等待唤醒机制:
什么是等待唤醒机制:
就是在一个线程进行了规定操作后,就进入等待状态(wait()),等待其他线程执行完他们的代码后再将其唤醒(notify());在有多个线程进行等待时,如果需要,
可以使用notifyAll()来唤醒所有的等待线程
wait/notify就是线程间的一种协作机制
等待唤醒中的方法:
wait:线程不再活动,不再参与调度,进入wait set中,因此不会浪费CPU资源,也就不会去竞争锁了,这时的线程状态即使WAITING。
它还要等着别的线程执行一个特别的动作,也即是“通知(notify)”在这个对象上等待的线程从wait set中释放,重新进入到调度队列(read quene)中
notify:则选取所通知对象的wait set中的一个线程释放;例如,餐馆有空位置后,等候最久的顾客最先入座
notifAll:则释放所通知对象的wait set上的全部线程
如果能获取锁,线程就从WAITING状态编程RUNNABLE状态;
否则,从wait set出来,又进入entry set,线程就从WAITING状态变成BLOCKED(阻塞)状态
调用wait和notify方法需要注意的细节;
wait方法与notufy方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程
wait方法与notify方法是属于Object类的方法。因为:锁对象可以是任意对象,而任意对象的所属类都是继承了Object类
wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方法
--线程池
其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去频繁创建线程对象的操作,无需反复创建线程而消耗过多资源
--Lambda表达式
函数式编程思想
只要能获取到结果,谁去做,怎么做的都不重要,重视的是结果,不重视过程
面向对象的思想:
做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情
传统写法:
public class Demo01Runnable {
public static void main(String[] args) {
// 匿名内部类
Runnable task = new Runnable() {
@Override
public void run() { // 覆盖重写抽象方法
System.out.println("多线程任务执行!");
}};
new Thread(task).start(); // 启动线程
}
}
Lambda的更优写法
public clss Demo02Runnable{
public static void main(String[] args){
new Thread(() -> System.out.print("多线程任务执行!")).start();//启动线程
}
lambda标准格式:
组成部分:
一些参数
一个箭头
一段代码
格式:
(参数类型 参数名称) -> {代码语句}
小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用都好分隔
- >是新引入的语法格式,代表指向动作
大括号内的语法与传统方法体要求基本一致
Lambda的参数和返回值:
需求:
使用数组存储多个Person对象
对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
//传统写法
package com.itheima.test05;
import java.util.Arrays;
import java.util.Comparator;
public class LambdaPersonTest {
public static void main(String[] args) {
//传统写法
//创建数组
Person[] arr = {new Person("赵丽颖", 30),
new Person("高圆圆", 28),
new Person("范冰冰", 40)};
//按照年龄进行排序
Comparator<Person> comparator = new Comparator<>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
};
//数组排序
Arrays.sort(arr, comparator);
//遍历数组
for (Person person : arr) {
System.out.println(person);
}
}
}
Lambda写法:
package com.itheima.test05;
import java.util.Arrays;
import java.util.Comparator;
public class LambdaPersonTest {
public static void main(String[] args) {
//传统写法
//创建数组
Person[] arr = {new Person("赵丽颖", 30),
new Person("高圆圆", 28),
new Person("范冰冰", 40)};
//按照年龄进行排序
/*Comparator<Person> comparator = new Comparator<>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
};
//数组排序
Arrays.sort(arr, comparator);
//遍历数组
for (Person person : arr) {
System.out.println(person);
}*/
Arrays.sort(arr,((o1, o2) -> {
return o1.getAge()-o2.getAge();
}));
//遍历数组
for (Person person : arr) {
System.out.println(person);
}
}
}
Lambda省略格式:
省略规则:
小括号内参数类型可以省略;
如果小括号内有且仅有一个参数,则小括号可以省略
如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号
Lambda的使用前提:
使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法;
无论是JDK内置的Runnable、Comparator接口还是自定义的接口,只有当接口中的抽象方法存在且唯一是,才可以使用Lambda
使用Lambda必须具有上下文推断
也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例
注意:有且仅有一个抽象方法的接口,成为“函数式接口”。
|
|