什麼是設計模式
在軟件工程中,設計模式(design pattern)是對軟件設計中普遍存在(反覆出現)的各種問題 ,所提出的解決方案。
架構模式 – MVC – 分層
設計模式 – 提煉系統中的組件
代碼模式(成例 Idiom)
– 低層次,與編碼直接相關
– 如DCL
不變模式
一個類的內部狀態創建後,在整個生命期間都不會發生變化時,就是不變類
不變模式不需要同步
代碼示例:
public final class Product {
//確保無子類
private final String no;
//私有屬性,不會被其他對象獲取
private final String name;
//final保證屬性不會被2次賦值
private final double price;
//在創建對象時,必須指定數據
public Product(String no, String name, double price) {
super();
//因爲創建之後,無法進行修改
this.no = no;
this.name = name;
this.price = price;
}
public String getNo() {
return no;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
JDK中的不變類:
java.lang.String
java.lang.Boolean
java.lang.Byte
java.lang.Character
java.lang.Double
java.lang.Float
java.lang.Integer
java.lang.Long
java.lang.Short
Future模式
核心思想
異步調用
主線程可以獲取到目標線程的處理結果
與join()的區別
join():主線程需要阻塞直到目標線程執行結束
Future:啓動了目標線程之後主線程還可以繼續其他操作,直到需要取目標線程的處理結果的時候才進行等待。
主要構造:
代碼示例:
public interface Data {
public String getResult ();
}
public class FutureData implements Data {
protected RealData realdata = null; //FutureData是RealData的包裝
protected boolean isReady = false;
public synchronized void setRealData(RealData realdata) {
if (isReady) {
return;
}
this.realdata = realdata;
isReady = true;
notifyAll(); //RealData已經被注入,通知getResult()
}
public synchronized String getResult() { //會等待RealData構造完成
while (!isReady) {
try {
wait(); //一直等待,知道RealData被注入
} catch (InterruptedException e) {
}
}
return realdata.result; //由RealData實現
}
}
public class RealData implements Data {
protected final String result;
public RealData(String para) {
//RealData的構造可能很慢,需要用戶等待很久,這裏使用sleep模擬
StringBuffer sb=new StringBuffer();
for (int i = 0; i < 10; i++) {
sb.append(para);
try {
//這裏使用sleep,代替一個很慢的操作過程
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
result =sb.toString();
}
public String getResult() {
return result;
}
}
public class Client {
public Data request(final String queryStr) {
final FutureData future = new FutureData();
new Thread() {
public void run() {// RealData的構建很慢,
//所以在單獨的線程中進行
RealData realdata = new RealData(queryStr);
future.setRealData(realdata);
}
}.start();
return future; // FutureData會被立即返回
}
}
public static void main(String[] args) {
Client client = new Client();
//這裏會立即返回,因爲得到的是FutureData而不是RealData
Data data = client.request("name");
System.out.println("請求完畢");
try {
//這裏可以用一個sleep代替了對其他業務邏輯的處理
//在處理這些業務邏輯的過程中,RealData被創建,從而充分利用了等待時間
Thread.sleep(2000);
} catch (InterruptedException e) {
}
//使用真實的數據,數據如果沒準備好,這裏會進行阻塞
System.out.println("數據 = " + data.getResult());
}
JDK對Future模式的支持
代碼示例:
public class RealData implements Callable<String> {
private String para;
public RealData(String para){
this.para=para;
}
@Override
public String call() throws Exception {
StringBuffer sb=new StringBuffer();
for (int i = 0; i < 10; i++) {
sb.append(para);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
return sb.toString();
}
}
public class FutureMain {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//構造FutureTask
FutureTask<String> future = new FutureTask<String>(new RealData("a"));
ExecutorService executor = Executors.newFixedThreadPool(1);
//執行FutureTask,相當於上例中的 client.request("a") 發送請求
//在這裏開啓線程進行RealData的call()執行
executor.submit(future);
System.out.println("請求完畢");
try {
//這裏依然可以做額外的數據操作,這裏使用sleep代替其他業務邏輯的處理
Thread.sleep(2000);
} catch (InterruptedException e) {
}
//相當於data.getResult (),取得call()方法的返回值
//如果此時call()方法沒有執行完成,則依然會等待
System.out.println("數據 = " + future.get());
}
}
public class FutureMain2 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(1);
//執行FutureTask,相當於上例中的 client.request("a") 發送請求
//在這裏開啓線程進行RealData的call()執行
Future<String> future=executor.submit(new RealData("a"));
System.out.println("請求完畢");
try {
//這裏依然可以做額外的數據操作,這裏使用sleep代替其他業務邏輯的處理
Thread.sleep(2000);
} catch (InterruptedException e) {
}
//相當於data.getResult (),取得call()方法的返回值
//如果此時call()方法沒有執行完成,則依然會等待
System.out.println("數據 = " + future.get());
}
}
生產者消費者
生產者-消費者模式是一個經典的多線程設計模式。它爲多線程間的協作提供了良好的解決方案。 在生產者-消費者模式中,通常由兩類線程,即若干個生產者線程和若干個消費者線程。生產者線 程負責提交用戶請求,消費者線程則負責具體處理生產者提交的任務。生產者和消費者之間則通 過共享內存緩衝區進行通信。
主要角色:
類圖: