見pdf
等待喚醒機制
wait和notify
第二章 線程池
如果併發的線程數量很多,並且每個線程都是執行一個時間很短的任務就結束了,這樣頻繁創建線程就會大大降低 系統的效率,因爲頻繁創建線程和銷燬線程需要時間。
容器->集合
java.util.concurrent.Executor
線程池:JDK1.5之後提供的
java.util.concurrent.Executors:線程池的工廠類,用來生成線程池
Executors類中的靜態方法:
static ExecutorService newFixedThreadPool(int nThreads) 創建一個可重用固定線程數的線程池
參數:
int nThreads:創建線程池中包含的線程數量
返回值:
ExecutorService接口,返回的是ExecutorService接口的實現類對象,我們可以使用ExecutorService接口接收(面向接口編程)
java.util.concurrent.ExecutorService:線程池接口
用來從線程池中獲取線程,調用start方法,執行線程任務
submit(Runnable task) 提交一個 Runnable 任務用於執行
關閉/銷燬線程池的方法
void shutdown()
線程池的使用步驟:
1.使用線程池的工廠類Executors裏邊提供的靜態方法newFixedThreadPool生產一個指定線程數量的線程池
2.創建一個類,實現Runnable接口,重寫run方法,設置線程任務
3.調用ExecutorService中的方法submit,傳遞線程任務(實現類),開啓線程,執行run方法
4.調用ExecutorService中的方法shutdown銷燬線程池(不建議執行)
public class Demo01ThreadPool {
public static void main(String[] args) {
//1.使用線程池的工廠類Executors裏邊提供的靜態方法newFixedThreadPool生產一個指定線程數量的線程池
ExecutorService es = Executors.newFixedThreadPool(2);
//3.調用ExecutorService中的方法submit,傳遞線程任務(實現類),開啓線程,執行run方法
es.submit(new RunnableImpl());//pool-1-thread-1創建了一個新的線程執行
//線程池會一直開啓,使用完了線程,會自動把線程歸還給線程池,線程可以繼續使用
es.submit(new RunnableImpl());//pool-1-thread-1創建了一個新的線程執行
es.submit(new RunnableImpl());//pool-1-thread-2創建了一個新的線程執行
//4.調用ExecutorService中的方法shutdown銷燬線程池(不建議執行)
es.shutdown();
es.submit(new RunnableImpl());//拋異常,線程池都沒有了,就不能獲取線程了
}
}
第三章 lamada表達式
1、Runnable
實現多線程程序
public class Demo01Runnable {
public static void main(String[] args) {
//創建Runnable接口的實現類對象
RunnableImpl run = new RunnableImpl();
//創建Thread類對象,構造方法中傳遞Runnable接口的實現類
Thread t = new Thread(run);
//調用start方法開啓新線程,執行run方法
t.start();
//簡化代碼,使用匿名內部類,實現多線程程序
Runnable r = new Runnable(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 新線程創建了");
}
};
new Thread(r).start();
//簡化代碼
new Thread(new Runnable(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 新線程創建了");
}
}).start();
}
}
似乎只有方法體纔是關鍵
目的只有run方法
2、轉換編程思想
將 run 方法體內的代碼傳遞給 Thread 類知曉。
2014年3月Oracle所發佈的Java 8(JDK 1.8)中,加入了Lambda表達 式的重量級新特性,爲我們打開了新世界的大門。
函數式編程
留一個小括號()->一些代碼
new Thread(() ‐> System.out.println("多線程任務執行!")).start(); // 啓動線程
()接口中抽象方法的參數列表
3、
對匿名內部類的代替
package com.itheima.demo04.Lambda;
/*
需求:
給定一個廚子Cook接口,內含唯一的抽象方法makeFood,且無參數、無返回值。
使用Lambda的標準格式調用invokeCook方法,打印輸出“喫飯啦!”字樣
*/
public class Demo01Cook {
public static void main(String[] args) {
// 調用invokeCook方法,參數是Cook接口,傳遞Cook接口的匿名內部類對象
invokeCook(new Cook() {
@Override
public void makeFood() {
System.out.println("喫飯了");
}
});
// 使用Lambda表達式,簡化匿名內部類的書寫
invokeCook(()->{
System.out.println("喫飯了");
});
//優化省略Lambda
invokeCook(()-> System.out.println("喫飯了"));
}
//定義一個方法,參數傳遞Cook接口,方法內部調用Cook接口中的方法makeFood
public static void invokeCook(Cook cook){
cook.makeFood();
}
}
4、排序
lamada表達式
方法有參數就寫參數,()->是實現類方法的體現
Arrays.sort(arr,(Person o1, Person o2)->{
return o1.getAge()-o2.getAge();
});
//優化省略Lambda
Arrays.sort(arr,(o1, o2)->o1.getAge()-o2.getAge());
//遍歷數組
for (Person p : arr) {
System.out.println(p);
}
5、練習
invokeCalu(120,130,(int a,int b)->System.out.println("isheudi"));
是對匿名內部類的簡化的重要操作。
6、還可以省略
Lambda表達式:是可推導,可以省略
凡是根據上下文推導出來的內容,都可以省略書寫
可以省略的內容:
1.(參數列表):括號中參數列表的數據類型,可以省略不寫
2.(參數列表):括號中的參數如果只有一個,那麼類型和()都可以省略
3.{一些代碼}:如果{}中的代碼只有一行,無論是否有返回值,都可以省略({},return,分號)
注意:要省略{},return,分號必須一起省略
一個參數可以省略參數
new Thread(()->System.out.println(Thread.currentThread().getName()+" 新線程創建了")).start();
1. 使用Lambda必須具有接口,且要求接口中有且僅有一個抽象方法。
備註:有且僅有一個抽象方法的接口,稱爲“函數式接口”。