一、線程池
1、什麼是線程池
自定義的線程類不管是繼承Thread類還是實現Runnable接口,都需要重寫Run方法,而且每一個線程對象有且只能執行一次,之後就會被銷燬,使用起來就比較麻煩。
線程池是可以容納多個線程的容器,程序可以從線程池獲取線程來完成目標代碼,同時也可以將線程歸還給線程池,省去了創建線程和銷燬線程這樣非常繁瑣的操作。
2、線程池的使用
public static ExecutorService newFixedThreadPool(int nThreads);
得到一個線程對象,初始化參數是要求的當前線程池中的線程數
public Future submit(Runnable target);
從線程池中獲取一個線程對象,並且執行給定的Runnable接口實現類對象作爲執行目標
class MyThread implements Runnable {
@Override
public void run() {
System.out.println("Runnable接口實現類,線程目標代碼");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Demo1 {
public static void main(String[] args) {
// 1. 創建線程池對象
ExecutorService service = Executors.newFixedThreadPool(3);
// 2. 創建一個MyThread Runnable接口實現類對象
MyThread target = new MyThread();
// 3. 使用線程池對象中的一個線程,指定目標代碼
// 初始化線程數爲3,這裏使用的是線程池中已經存在的3個線程來執行代碼
service.submit(target);
service.submit(target);
service.submit(target);
// 因爲原本的3個線程都在被使用中,這裏需要等待3個線程執行完畢,出現空閒線程
// 來執行對應的目標代碼
service.submit(target);
service.submit(target);
// 4. 關閉線程池
// 一般不用關閉線程池,會隨着程序的退出而關閉
// service.shutdown();
}
}
3、引入Lambda表達式
線程池的 submit() 方法需要一個Runnable接口的實現類對象,像上面直接自定義一個Runnable接口實現類比較麻煩,會想到使用匿名內部類直接傳入 submit() 方法中。其實此處使用Lambda表達式來代替匿名內部類更加簡潔。
public class Demo2 {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
//使用匿名內部類
service.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
// 使用lambda表達式
service.submit(() -> System.out.println(Thread.currentThread().getName()));
}
}
二、Lambda表達式
1、使用前提
- 有且只有一個缺省屬性爲public abstract方法的接口,例如 Comparator接口,Runnable接口。
- 使用lambda表達式是有一個前後要求約束的,方法的參數爲接口類型,或者說局部變量使用調用方法,可以使用lambda表達式。
- 有且只有一個抽象方法的接口,稱之爲函數式接口。
2、無參數無返回值的情況
interface Cook {
void cooking();
}
public class Demo1 {
public static void main(String[] args) {
//使用匿名內部類
invokeCook(new Cook() {
@Override
public void cooking() {
System.out.println("鍋包肉");
}
});
//使用Lambda表達式,規範形式
invokeCook(() -> {
System.out.println("紅燒排骨");
});
//使用Lambda表達式,極簡形式
invokeCook(() -> System.out.println("西紅柿炒雞蛋"));
}
/**
* 執行Cook實現類對象方法
*
* @param cook Cook接口的實現類對象
*/
public static void invokeCook(Cook cook) {
cook.cooking();
}
}
3、有參數有返回值的情況
interface A {
float add(int num1, float num2);
}
public class Demo2 {
public static void main(String[] args) {
//使用匿名內部類
System.out.println(new A() {
@Override
public float add(int num1, float num2) {
return num1 + num2;
}
}.add(5, 13.5F));
/*
* 使用Lambda表達式
* 1. 參數的數據類型可以省略
* 2. 實現的代碼非一行,可以在大括號內完成所有目標
*/
test(5, 13.5F, (num1, num2) -> {
float sum = num1 + num2;
return sum;
});
}
public static void test(int num1, float num2, A a) {
System.out.println(a.add(num1, num2));
}
}