1)、当一个工作需要多个线程同时配合完成,这就需要多个线程间进行通信,以保证这个工作能够完整的完成,这种互相配合的方式就叫做线程间通信
1)、等待唤醒机制就是线程间通信的一种体现
2)、工作形式:
一个线程做一些准备工作
另一个线程做正常的工作
由于线程在运行时是无序的,第二个线程工作时,有可能第一个线程的准备工作还没有做好。这时就需要第二个线程主动的进入等待,然后第一个线程进入开始准备工作,准备工作完成后,唤醒第二个线程开始正常工作
1)、没有线程间通信的实现:
包子生产者可能没有生产好包子,消费者就会来“拿“包子,这时消费者可能会拿到空值,所以就需要线程间通信
2)、加入线程间通信的实现:
加入线程间通信后就实现了生产者生产出包子,才唤醒消费者来“拿”包子,这样消费者就不会拿到空值
1)、线程池:存储了若干多个线程对象的一个容器
2)、对于一个线程对象只能启动一次,再次使用就要再次创建一个线程对象,创建线程对象是耗时操作,程序中要反复使用同一个线程,就要反复创建线程,效率低
3)、线程池思想:在程序启动时,会先创建若干多的线程对象。并存储在一个“线程池”。如果有需要时,取出一个线程对象,并执行它。执行完毕,线程池会回收这个线程对象,如果再次需要时,可以再次取出,并执行,所以,线程池中的线程对象是可以反复使用的。这样就避免 了反复创建线程对象,从而提高了程序的执行效率
线程池类:ExecutorService:缓存大量的线程对象,并可以反复重用他们
有重用价值的线程对象才值得放在线程池中
public static void main(String[] args) {
//不使用线程池--两次使用一个线程,供需要10秒
/*MyThread t = new MyThread();//5秒
t.start();
//第二次再次想使用这个线程
t = new MyThread();//5秒
t.start();*/
//使用线程池
//创建线程池对象
ExecutorService service = Executors.newFixedThreadPool(2);
//创建线程对象
MyThread t = new MyThread();//5秒
//第一次执行此线程--交给"线程池”去执行,线程池执行后,会将此线程对象"缓存",可以重用
service.submit(t);
//第二次执行此线程
service.submit(t);
//第三次执行此线程
service.submit(t);
//.....
//关闭线程池
service.shutdown();
}
对线程的匿名内部类的简写形式
public class Demo {
public static void main(String[] args) {
//1.方式一:制作Runnable子类的方式
MyRunnable myRunnable = new MyRunnable();
Thread t = new Thread(myRunnable);
t.start();
//2.方式二:匿名内部类的方式
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
}
}
});
t2.start();
//3.方式三:使用Lambda的方式
Thread t3 = new Thread(()->{
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
}
});
t3.start();
}
}
1)、编程思想转换:将“以什么形式做”转换为“怎么做”
2)、“函数式编程”思想:当调用的方法需要一个接口类型时,就可以考虑直接传入一个代替的函数(方法),无用的语句直接省略
使用前提:(具备以下条件,才可以使用Lambda表达式)
1)、必须要是一个接口类型;
2)、且接口中有且只有一个抽象方法–函数式接口
标准格式;
1)、一对小括号,内容是形参
2)、一个右箭头:->
3)、一对大括号–方法体
举例:
1.new Thread(()->{System.out.println("线程开始运行...");}).start();
//2.使用匿名内部类:
Runnable r = new Runnable(){
public void run(){
System.out.println("线程开始运行");
}
};
Thread t = new Thread(r);
t.start();
//使用Lambda:
Runnable r = ()->{System.out.println("线程开始运行...");};
Thread t = new Thread(r);
t.start();
//函数式接口--有,且只有一个抽象方法
interface IA{
public void show();
}
class SubClass implements IA{
@Override
public void show() {
System.out.println("子类是show()....");
}
}
public class Demo {
public static void main(String[] args) {
//1.传递子类对象
fun(new SubClass());
//2.使用匿名内部类
fun(new IA(){
@Override
public void show() {
System.out.println("匿名内部子类的show()....");
}
});
//3.Lambda表达式
fun(()->{
System.out.println("Lambda的show()....");
});
}
public static void fun(IA ia) {
ia.show();
}
}
1)、自定义接口
interface IA{
public int calc(int a, int b);
}
public class Demo {
public static void main(String[] args) {
//2.匿名子类对象
fun(new IA(){
@Override
public int calc(int a, int b) {
return a + b;
}
},10,20);
//3.使用Lambda
fun((int x,int y)->{return x * y;},10,20);
}
public static void fun(IA ia, int m, int n) {
int result = ia.calc(m, n);
System.out.println("结果是:" + result);
}
}
2)、类库中接口的例子
public class Demo {
public static void main(String[] args) {
List stuList = new ArrayList<>();
stuList.add(new Student("张三1", 17));
stuList.add(new Student("张三2", 16));
stuList.add(new Student("张三3", 19));
stuList.add(new Student("张三4", 15));
//1.使用匿名内部类的方式
Collections.sort(stuList, new Comparator() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
});
//2.使用Lambda
Collections.sort(stuList,(Student o1, Student o2)->{
return o1.getAge() - o2.getAge();
});
System.out.println(stuList);
}
}
interface IA{
public void show(int a,int b);
}
public class Demo {
public static void main(String[] args) {
//1.匿名子类
fun(new IA() {
@Override
public void show(int a, int b) {
System.out.println(a + b);
}
}, 10, 20);
//2.使用Lambda
fun((int a, int b) -> {System.out.println(a * b); }, 10, 20);
}
public static void fun(IA a, int m, int n) {
a.show(m, n);
}
}
例子:
//2.Lambda表达式--完整格式
fun((int x, int y) -> {return x + y;}, 10, 20);
//3.简写的Lambda
fun((x, y) -> x + y, 10, 20);
省略规则:
1)、形参:Lambda中的形参类型都可以省略
2)、形参:如果只有一个参数,形参类型和小括号都可以省略
(要省略小括号,必须省略形参类型)
3)、方法体:如果方法体中只有一条语句,可以应用省略规则:
有返回值:可以省略大括号、return关键、分号(要省全省)
无返回值:可以省略大括号、分号(要省全省)
[ ] 能够理解线程通信概念
多个线程共同协作完成同一个任务,就需要线程间进行通信
[ ] 能够理解等待唤醒机制
等待唤醒机制是线程间通信的一种体现
一个线程在执行时发现准备工作不满足,就会进入等待状态,另一个线程开始做准备工作,准备工作完成后,就会唤醒等待中的线程
[ ] 能够描述Java中线程池运行原理
将多个复用的线程对象放在一个容器中,这个容器就是线程池
[ ] 能够理解函数式编程相对于面向对象的优点
函数式编程思想更在意与怎么做,而不是以什么形式去做
[ ] 能够掌握Lambda表达式的标准格式
new Thread(()->{方法体;}).start();
[ ] 能够使用Lambda标准格式使用Runnable与Comparator接口
[ ] 能够掌握Lambda表达式的省略格式与规则
[ ] 能够使用Lambda省略格式使用Runnable与Comparator接口
[ ] 能够通过Lambda的标准格式使用自定义的接口(有且仅有一个抽象方法)
[ ] 能够通过Lambda的省略格式使用自定义的接口(有且仅有一个抽象方法)
[ ] 能够明确Lambda的两项使用前提