最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 高并發(fā)七:并發(fā)設(shè)計(jì)模型詳解

 更新時(shí)間:2016年09月09日 18:08:53   作者:Hosee  
本文主要介紹Java高并發(fā) 并發(fā)設(shè)計(jì)模型的知識(shí),這里主要講解 1. 什么是設(shè)計(jì)模式 2. 單例模式 3. 不變模式 4. Future模式 5. 生產(chǎn)者消費(fèi)者,有需要的小伙伴可以參考下

1. 什么是設(shè)計(jì)模式

在軟件工程中,設(shè)計(jì)模式(design pattern)是對(duì)軟件設(shè)計(jì)中普遍存在(反復(fù)出現(xiàn))的各種問(wèn)題 ,所提出的解決方案。這個(gè)術(shù)語(yǔ)是由埃里?!べが敚‥rich Gamma)等人在1990年代從建筑設(shè)計(jì)領(lǐng) 域引入到計(jì)算機(jī)科學(xué)的。

著名的4人幫: Erich Gamma,Richard Helm, Ralph Johnson ,John Vlissides (Gof)

《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》收錄23種模式

2. 單例模式

單例對(duì)象的類必須保證只有一個(gè)實(shí)例存在。許多時(shí)候整個(gè)系統(tǒng)只需要擁有一個(gè)的全局對(duì)象,這樣有利于我們協(xié)調(diào)系統(tǒng)整體的行為

比如:全局信息配置

單例模式最簡(jiǎn)單的實(shí)現(xiàn):

public class Singleton {
 private Singleton() {
 System.out.println("Singleton is create");
 }
 private static Singleton instance = new Singleton();
 public static Singleton getInstance() {
 return instance;
 }
}

由私有構(gòu)造方法和static來(lái)確定唯一性。

缺點(diǎn):何時(shí)產(chǎn)生實(shí)例 不好控制

雖然我們知道,在類Singleton第一次被加載的時(shí)候,就產(chǎn)生了一個(gè)實(shí)例。

但是如果這個(gè)類中有其他屬性

public class Singleton {
 public static int STATUS=1; 
 private Singleton() {
 System.out.println("Singleton is create");
 }
 private static Singleton instance = new Singleton();
 public static Singleton getInstance() {
 return instance;
 }
}

當(dāng)使用

System.out.println(Singleton.STATUS);

這個(gè)實(shí)例就被產(chǎn)生了。也許此時(shí)你并不希望產(chǎn)生這個(gè)實(shí)例。

如果系統(tǒng)特別在意這個(gè)問(wèn)題,這種單例的實(shí)現(xiàn)方法就不太好。

第二種單例模式的解決方式:

public class Singleton {
 private Singleton() {
 System.out.println("Singleton is create");
 }
 private static Singleton instance = null;
 public static synchronized Singleton getInstance() {
 if (instance == null)
 instance = new Singleton();
 return instance;
 }
}

讓instance只有在調(diào)用getInstance()方式時(shí)被創(chuàng)建,并且通過(guò)synchronized來(lái)確保線程安全。
這樣就控制了何時(shí)創(chuàng)建實(shí)例。

這種方法是延遲加載的典型。

但是有一個(gè)問(wèn)題就是,在高并發(fā)的場(chǎng)景下性能會(huì)有影響,雖然只有一個(gè)判斷就return了,但是在并發(fā)量很高的情況下,或多或少都會(huì)有點(diǎn)影響,因?yàn)槎家ツ胹ynchronized的鎖。

為了高效,有了第三種方式:

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;
 }
}

由于加載一個(gè)類時(shí),其內(nèi)部類不會(huì)被加載。這樣保證了只有調(diào)用getInstance()時(shí)才會(huì)產(chǎn)生實(shí)例,控制了生成實(shí)例的時(shí)間,實(shí)現(xiàn)了延遲加載。

并且去掉了synchronized,讓性能更優(yōu),用static來(lái)確保唯一性。

3. 不變模式

一個(gè)類的內(nèi)部狀態(tài)創(chuàng)建后,在整個(gè)生命期間都不會(huì)發(fā)生變化時(shí),就是不變類

不變模式不需要同步

創(chuàng)建一個(gè)不變的類:

public final class Product {
 // 確保無(wú)子類
 private final String no;
 // 私有屬性,不會(huì)被其他對(duì)象獲取
 private final String name;
 // final保證屬性不會(huì)被2次賦值
 private final double price;

 public Product(String no, String name, double price) {
 // 在創(chuàng)建對(duì)象時(shí),必須指定數(shù)據(jù)
 super();
 // 因?yàn)閯?chuàng)建之后,無(wú)法進(jìn)行修改
 this.no = no;
 this.name = name;
 this.price = price;
 }

 public String getNo() {
 return no;
 }

 public String getName() {
 return name;
 }

 public double getPrice() {
 return price;
 }

}

Java中不變的模式的案例有:

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 

4. Future模式

核心思想是異步調(diào)用

非異步:

異步:

第一次的call_return由于任務(wù)還沒(méi)完成,所以返回的是一個(gè)空的。

但是這個(gè)返回類似于購(gòu)物中的訂單,將來(lái)可以根據(jù)這個(gè)訂單來(lái)得到一個(gè)結(jié)果。

所以這個(gè)Future模式意思就是,“未來(lái)”可以得到,就是指這個(gè)訂單或者說(shuō)是契約,“承諾”未來(lái)就會(huì)給結(jié)果。

Future模式簡(jiǎn)單的實(shí)現(xiàn):

調(diào)用者得到的是一個(gè)Data,一開始可能是一個(gè)FutureData,因?yàn)镽ealData構(gòu)建很慢。在未來(lái)的某個(gè)時(shí)間,可以通過(guò)FutureData來(lái)得到RealData。

代碼實(shí)現(xiàn):


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已經(jīng)被注入,通知getResult() 
 } 
 public synchronized String getResult()//會(huì)等待RealData構(gòu)造完成 
 { 
 while (!isReady) { 
 try {  
 wait(); //一直等待,知道RealData被注入 
 } catch (InterruptedException e) { 
 } 
 } 
 return realdata.result; //由RealData實(shí)現(xiàn) 
 } 
}
public class RealData implements Data {
 protected final String result;
 public RealData(String para) {
 // RealData的構(gòu)造可能很慢,需要用戶等待很久,這里使用sleep模擬
 StringBuffer sb = new StringBuffer();
 for (int i = 0; i < 10; i++) {
 sb.append(para);
 try {
 // 這里使用sleep,代替一個(gè)很慢的操作過(guò)程
 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的構(gòu)建很慢, 
 //所以在單獨(dú)的線程中進(jìn)行 
 RealData realdata = new RealData(queryStr);  
 future.setRealData(realdata); 
 }    
 }.start(); 
 return future; // FutureData會(huì)被立即返回 
 } 
}
public static void main(String[] args) {
 Client client = new Client();
 // 這里會(huì)立即返回,因?yàn)榈玫降氖荈utureData而不是RealData
 Data data = client.request("name");
 System.out.println("請(qǐng)求完畢");
 try {
 // 這里可以用一個(gè)sleep代替了對(duì)其他業(yè)務(wù)邏輯的處理
 // 在處理這些業(yè)務(wù)邏輯的過(guò)程中,RealData被創(chuàng)建,從而充分利用了等待時(shí)間
 Thread.sleep(2000);
 } catch (InterruptedException e) {
 }
 // 使用真實(shí)的數(shù)據(jù)
 System.out.println("數(shù)據(jù) = " + data.getResult());
 }

JDK中也有多Future模式的支持:


接下來(lái)使用JDK提供的類和方法來(lái)實(shí)現(xiàn)剛剛的代碼:

import java.util.concurrent.Callable;

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();
 }
}

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class FutureMain {
 public static void main(String[] args) throws InterruptedException,
 ExecutionException {
 // 構(gòu)造FutureTask
 FutureTask<String> future = new FutureTask<String>(new RealData("a"));
 ExecutorService executor = Executors.newFixedThreadPool(1);
 // 執(zhí)行FutureTask,相當(dāng)于上例中的 client.request("a") 發(fā)送請(qǐng)求
 // 在這里開啟線程進(jìn)行RealData的call()執(zhí)行
 executor.submit(future);
 System.out.println("請(qǐng)求完畢");
 try {
 // 這里依然可以做額外的數(shù)據(jù)操作,這里使用sleep代替其他業(yè)務(wù)邏輯的處理
 Thread.sleep(2000);
 } catch (InterruptedException e) {
 }
 // 相當(dāng)于data.getResult (),取得call()方法的返回值
 // 如果此時(shí)call()方法沒(méi)有執(zhí)行完成,則依然會(huì)等待
 System.out.println("數(shù)據(jù) = " + future.get());
 }
}

這里要注意的是FutureTask是即具有 Future功能又具有Runnable功能的類。所以又可以運(yùn)行,最后還能get。
當(dāng)然如果在調(diào)用到future.get()時(shí),真實(shí)數(shù)據(jù)還沒(méi)準(zhǔn)備好,仍然會(huì)產(chǎn)生阻塞狀況,直到數(shù)據(jù)準(zhǔn)備完成。

當(dāng)然還有更加簡(jiǎn)便的方式:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FutureMain2 {
 public static void main(String[] args) throws InterruptedException,
 ExecutionException {
 ExecutorService executor = Executors.newFixedThreadPool(1);
 // 執(zhí)行FutureTask,相當(dāng)于上例中的 client.request("a") 發(fā)送請(qǐng)求
 // 在這里開啟線程進(jìn)行RealData的call()執(zhí)行
 Future<String> future = executor.submit(new RealData("a"));
 System.out.println("請(qǐng)求完畢");
 try {
 // 這里依然可以做額外的數(shù)據(jù)操作,這里使用sleep代替其他業(yè)務(wù)邏輯的處理
 Thread.sleep(2000);
 } catch (InterruptedException e) {
 }
 // 相當(dāng)于data.getResult (),取得call()方法的返回值
 // 如果此時(shí)call()方法沒(méi)有執(zhí)行完成,則依然會(huì)等待
 System.out.println("數(shù)據(jù) = " + future.get());
 }
}

由于Callable是有返回值的,可以直接返回future對(duì)象。

5. 生產(chǎn)者消費(fèi)者

生產(chǎn)者-消費(fèi)者模式是一個(gè)經(jīng)典的多線程設(shè)計(jì)模式。它為多線程間的協(xié)作提供了良好的解決方案。 在生產(chǎn)者-消費(fèi)者模式中,通常由兩類線程,即若干個(gè)生產(chǎn)者線程和若干個(gè)消費(fèi)者線程。生產(chǎn)者線 程負(fù)責(zé)提交用戶請(qǐng)求,消費(fèi)者線程則負(fù)責(zé)具體處理生產(chǎn)者提交的任務(wù)。生產(chǎn)者和消費(fèi)者之間則通 過(guò)共享內(nèi)存緩沖區(qū)進(jìn)行通信。

以前寫過(guò)一篇用Java來(lái)實(shí)現(xiàn)生產(chǎn)者消費(fèi)者的多種方法,這里就不多闡述了。

相關(guān)文章

  • Java實(shí)現(xiàn)excel動(dòng)態(tài)列導(dǎo)出的示例代碼

    Java實(shí)現(xiàn)excel動(dòng)態(tài)列導(dǎo)出的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)excel動(dòng)態(tài)列導(dǎo)出,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • Spring事務(wù)傳播屬性和隔離級(jí)別詳細(xì)介紹

    Spring事務(wù)傳播屬性和隔離級(jí)別詳細(xì)介紹

    這篇文章主要介紹了Spring事務(wù)傳播屬性和隔離級(jí)別詳細(xì)介紹,同時(shí)涉及傳播行為介紹,超時(shí)設(shè)置等相關(guān)內(nèi)容,需要的朋友可以參考下。
    2017-09-09
  • Java并發(fā)編程之線程創(chuàng)建介紹

    Java并發(fā)編程之線程創(chuàng)建介紹

    這篇文章主要介紹了Java并發(fā)編程之線程創(chuàng)建,進(jìn)程是代碼在數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,線程則是一個(gè)實(shí)體,一個(gè)進(jìn)程中至少有一個(gè)線程,下文更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-04-04
  • Netty分布式server啟動(dòng)流程N(yùn)io創(chuàng)建源碼分析

    Netty分布式server啟動(dòng)流程N(yùn)io創(chuàng)建源碼分析

    這篇文章主要介紹了Netty分布式server啟動(dòng)流程N(yùn)io創(chuàng)建源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • Spring中的@ResponseStatus使用

    Spring中的@ResponseStatus使用

    這篇文章主要介紹了Spring中的@ResponseStatus使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • java數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的實(shí)例應(yīng)用

    java數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的實(shí)例應(yīng)用

    大家好,本篇文章主要講的是java數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的實(shí)例應(yīng)用,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • Java三元表達(dá)式使用及注意事項(xiàng)詳解

    Java三元表達(dá)式使用及注意事項(xiàng)詳解

    這篇文章主要介紹了Java三元表達(dá)式使用及注意事項(xiàng)的相關(guān)資料,Java中的三元運(yùn)算符是一種簡(jiǎn)潔的條件語(yǔ)句,它可以根據(jù)一個(gè)條件來(lái)選擇兩個(gè)不同的值中的一個(gè),適用于簡(jiǎn)單的條件賦值場(chǎng)景,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • java設(shè)計(jì)模式之簡(jiǎn)單工廠模式詳解

    java設(shè)計(jì)模式之簡(jiǎn)單工廠模式詳解

    這篇文章主要介紹了java設(shè)計(jì)模式之簡(jiǎn)單工廠模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • SpringBoot+Mybatis實(shí)現(xiàn)Mapper接口與Sql綁定幾種姿勢(shì)

    SpringBoot+Mybatis實(shí)現(xiàn)Mapper接口與Sql綁定幾種姿勢(shì)

    通常我們?cè)谑褂肕ybatis進(jìn)行開發(fā)時(shí),會(huì)選擇xml文件來(lái)寫對(duì)應(yīng)的sql,然后將Mapper接口與sql的xml文件建立綁定關(guān)系,然后在項(xiàng)目中調(diào)用mapper接口就可以執(zhí)行對(duì)應(yīng)的sql,感興趣的可以學(xué)習(xí)一下
    2021-09-09
  • Java中用爬蟲進(jìn)行解析的實(shí)例方法

    Java中用爬蟲進(jìn)行解析的實(shí)例方法

    在本篇文章里小編給大家整理的是一篇關(guān)于Java中用爬蟲進(jìn)行解析的實(shí)例方法,有需要的朋友們可以學(xué)習(xí)參考下。
    2020-12-12

最新評(píng)論

文成县| 泾川县| 嘉鱼县| 赤城县| 和静县| 太白县| 赤水市| 扶沟县| 梁平县| 长垣县| 黄山市| 天峻县| 葵青区| 五指山市| 米泉市| 阿巴嘎旗| 容城县| 贵溪市| 湘西| 兴国县| 恭城| 棋牌| 徐汇区| 田东县| 米易县| 搜索| 景宁| 西林县| 台东市| 辰溪县| 外汇| 东丰县| 洞头县| 正镶白旗| 乌兰县| 雅江县| 衡阳市| 盘锦市| 江源县| 新宁县| 开远市|