1. java 中的多線程設計模式有哪些?java
答: 單例模式,不變類,Future,生產消費者設計模式
2. 比較好的單例模式安全
2.1 線程安全且 具備懶加載的單例,缺點:性能不太好多線程
public class LazySingleton { private LazySingleton() { System.out.println("LazySingleton is create"); } private static LazySingleton instance = null; public static synchronized LazySingleton getInstance() { if (instance == null) instance = new LazySingleton(); return instance; } }
2.2 高性能,懶加載,且沒有線程安全問題(使用內部類建立)app
public class StaticSingleton { private StaticSingleton(){ System.out.println("StaticSingleton is create"); } private static class SingletonHolder { private static StaticSingleton instance = new StaticSingleton(); } public static StaticSingleton getInstance() { return SingletonHolder.instance; } }
3. 不變模式異步
特色:一個類的內部狀態建立後,在整個生命期間都不會發生變化時,就是不變類 性能
不變模式不須要同步this
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; } }
4. Future異步加載模式spa
總結:調用客戶端得到數據,生成一個殼子並返回(此時調用殼子的獲取數據方法會阻塞),同時開啓線程裝配數據,完成以後注入到 殼子中,並通知線程返 回結果線程
效果:第一次要數據的時候返回一個殼子,用戶拿着殼子獲取數據時,若此時數據沒裝好,就會阻塞
3.1
public interface Data { public String getResult (); }
3.2
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實現 } }
3.3
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; } }
3.4
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會被當即返回 } }
3.5 使用該組件:
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()); }
4. 生產消費者模式