自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

看我在項(xiàng)目里怎么用設(shè)計(jì)模式,這么學(xué)設(shè)計(jì)模式也太簡(jiǎn)單了

開發(fā) 前端
可能很多人都聽說過這個(gè)單例設(shè)計(jì)模式了,甚至都寫的賊溜,但是今天給大家說說用這個(gè)單例設(shè)計(jì)模式,咱們是怎么把代碼的性能大幅度提升的,單例模式跟代碼性能的關(guān)系,恐怕很多兄弟還沒認(rèn)真研究過呢!

大家好,今天給大家分享一個(gè)寫代碼的設(shè)計(jì)模式,就是我們最最耳熟能詳?shù)膯卫O(shè)計(jì)模式。

可能很多人都聽說過這個(gè)單例設(shè)計(jì)模式了,甚至都寫的賊溜,但是今天給大家說說用這個(gè)單例設(shè)計(jì)模式,咱們是怎么把代碼的性能大幅度提升的,單例模式跟代碼性能的關(guān)系,恐怕很多兄弟還沒認(rèn)真研究過呢!

一次請(qǐng)求執(zhí)行流程

首先我們先來看看什么叫做單例模式,要理解單例模式,我們就得先說說不用單例模式的時(shí)候,我們平時(shí)創(chuàng)建對(duì)象是怎么弄的。

平時(shí)創(chuàng)建對(duì)象這個(gè)簡(jiǎn)單吧,比如我們搞一個(gè)對(duì)外的 web 接口,然后再接口收到一個(gè)請(qǐng)求的時(shí)候,就創(chuàng)建一個(gè)對(duì)象。

這個(gè)偽代碼如下:

@RestController("/user")
public class Controller {

private UserService userService;

@RequestMapping("/create")
public Response create(CreateUserRequest request){
User user = new User(request);

UserService userService = new UserService();
userService.add(user);

return Response.success();
}

}

上面那段代碼極為的簡(jiǎn)單,假設(shè)你有一個(gè) Controller 對(duì)外提供一個(gè) http 接口,然后每次你通過瀏覽器發(fā)送一個(gè)創(chuàng)建用戶的請(qǐng)求。

也就是針對(duì)/user/create 這個(gè) url 的請(qǐng)求,發(fā)送一個(gè) CreateUserRequest 請(qǐng)求參數(shù),代碼里就會(huì)通過 new 關(guān)鍵字,搞出來一個(gè) User 對(duì)象。

然后再通過new關(guān)鍵字創(chuàng)建一個(gè) UserService 組件來,接著把 User 對(duì)象交給 UserService 組件去插入這個(gè)用戶數(shù)據(jù)到數(shù)據(jù)庫(kù)里去,這段代碼基本但凡是懂 java 的應(yīng)該都能看懂。

但是這里有一個(gè)問題,大家知道每次處理請(qǐng)求的時(shí)候,這段代碼運(yùn)行他會(huì)干什么事情嗎?

其實(shí)有一個(gè)最關(guān)鍵的點(diǎn)就是,他每次請(qǐng)求過來都會(huì)在內(nèi)存里創(chuàng)建一個(gè) User 對(duì)象和一個(gè) UserService 對(duì)象,那這些對(duì)象是如何創(chuàng)建的呢?

java 代碼是如何運(yùn)行的?

下面就得給大家來揭秘一下這個(gè)代碼運(yùn)行的底層原理了,首先呢,當(dāng)我們啟動(dòng)一個(gè) Java 程序的時(shí)候,一定會(huì)啟動(dòng)一個(gè) JVM 進(jìn)程。

比如說上面那段代碼,你可能是通過 SpringBoot 這類框架用 main 方法啟動(dòng)的,也可能是把他打包以后放到 Tomcat 里去運(yùn)行的。

如果你是直接運(yùn)行 main 方法來啟動(dòng)的,那么就會(huì)直接啟動(dòng)一個(gè) JVM 進(jìn)程,如果你是把代碼打包以后放 Tomcat 里運(yùn)行的,那么 Tomcat 自己本身就是一個(gè) JVM 進(jìn)程。

如下圖:

接著呢,其實(shí)你啟動(dòng)的 JVM 進(jìn)程,會(huì)把你寫好的代碼加載到內(nèi)存里來然后運(yùn)行你寫的代碼,你的代碼運(yùn)行起來以后,他就可以干你希望他干的事情了,比如說接收瀏覽器發(fā)送的 http 請(qǐng)求,然后創(chuàng)建一些對(duì)象,插入數(shù)據(jù)庫(kù)等等。

如下圖所示:

那么這個(gè)時(shí)候,有一個(gè)很關(guān)鍵的點(diǎn),就是你的代碼運(yùn)行的時(shí)候用 new User() 和 new UserService() 創(chuàng)建出來的對(duì)象扔哪兒去了?

很簡(jiǎn)單,你的 JVM 進(jìn)程是有一塊自己的內(nèi)存區(qū)域可以用的,而且就他可以用,這塊區(qū)域叫做堆內(nèi)存。

這就類似于咱們自己家蓋個(gè)小別墅,弄一塊院子自己可以在里面種花種草一樣,別人不能在你家院子里種黃瓜和大蒜,對(duì)不對(duì)?

如下圖:

那么接著呢,上面我們寫的那段代碼,大家注意一下,每次收到一個(gè)請(qǐng)求,都會(huì)創(chuàng)建一個(gè) User 對(duì)象和一個(gè) UserService 對(duì)象,對(duì)不對(duì)?

所以說,隨著你不停的發(fā)送請(qǐng)求不停的發(fā)送請(qǐng)求,咱們的代碼是不是會(huì)不停的創(chuàng)建對(duì)象不停的創(chuàng)建對(duì)象,然后咱們的堆內(nèi)存里,對(duì)象是不是就會(huì)變的越來越多,越來越多?

如下圖:

堆內(nèi)存滿了后怎么辦?

那么我問大家一個(gè)問題,堆內(nèi)存是一塊內(nèi)存空間,他是可以無限制的一直放入對(duì)象的嗎?

當(dāng)然不是了,當(dāng)你的對(duì)象越來越多,太多的時(shí)候,就會(huì)把這塊內(nèi)存空間給塞滿,塞滿了以后他就放不下新的對(duì)象了,這個(gè)時(shí)候怎么辦呢?

他會(huì)觸發(fā)一個(gè)垃圾回收的動(dòng)作,就是 JVM 進(jìn)程自己偷偷摸摸開了一個(gè)垃圾回收線程,這個(gè)線程就專門盯著我們的堆內(nèi)存,感覺他快滿了,就把里面的對(duì)象清理掉一部分,這就叫做垃圾回收。

如下圖:

但是每次垃圾回收都有一個(gè)問題,他因?yàn)橐謇淼粢恍?duì)象,所以往往會(huì)在清理對(duì)象的時(shí)候,避免你再創(chuàng)建新的對(duì)象了。

不然就跟你媽媽打掃你的房間一樣,人家一邊在打掃垃圾,結(jié)果你還不停的吃東西往地下扔垃圾,你媽媽不打你屁股才怪,對(duì)吧?所以一般垃圾回收的時(shí)候,會(huì)讓 JVM 進(jìn)程停止工作,別創(chuàng)建新的對(duì)象了。

如下圖:

那么在垃圾回收進(jìn)行中,JVM 進(jìn)程停止運(yùn)行的這個(gè)期間,是不是會(huì)導(dǎo)致一個(gè)問題,那就是你的用戶發(fā)送過來的請(qǐng)求就沒人處理了。

沒錯(cuò),這個(gè)時(shí)候用戶會(huì)感覺每次發(fā)送請(qǐng)求那是卡住,一直卡著沒有返回,此時(shí)系統(tǒng)性能是處于一個(gè)極差的狀態(tài)的。

如下圖:

用單例模式如何優(yōu)化系統(tǒng)性能呢?

那么這個(gè)時(shí)候問題來了,回到這篇文章的主體,就是用單例模式如何優(yōu)化系統(tǒng)性能呢?

其實(shí)針對(duì)上面的問題,很多小伙伴可能已經(jīng)發(fā)現(xiàn)了,如果想要優(yōu)化系統(tǒng)性能,有一個(gè)關(guān)鍵的點(diǎn)就是盡量創(chuàng)建少一些的對(duì)象,避免堆內(nèi)存頻繁的塞滿,也就可以避免頻繁的垃圾回收,更可以避免頻繁的 JVM 進(jìn)程停頓,進(jìn)而避免系統(tǒng)請(qǐng)求頻繁的卡頓無響應(yīng)。

那如何少創(chuàng)建一些對(duì)象呢?單例模式就是一個(gè)很好的辦法了,對(duì)于我們來說,其實(shí)完全可以讓 UserService 這個(gè)對(duì)象就只創(chuàng)建一次,不要每次請(qǐng)求重復(fù)的創(chuàng)建他。

讓一個(gè)對(duì)象就創(chuàng)建一次,就是單例模式,單例模式有很多種寫法,其中一種寫法如下:

@RestController("/user")
public class Controller {
private UserService userService;
@RequestMapping("/create")
public Response create(CreateUserRequest request){
User user = new User(request);

UserService userService = UserSerivce.getInstance();
userService.add(user);

return Response.success();
}
}
public class UserService {
private UserService(){}
private static class Singleton {
static UserService userService = new UserService();
}
public static UserService getInstance(){
return Singleton.userService;
}

}

大家可以看到上面的代碼,我們?cè)?UserService 中定義了一個(gè)私有化的靜態(tài)內(nèi)部類 Singleton,在 Singleton 里定義了一個(gè)靜態(tài)變量 UserService 對(duì)象。

這樣的話,Singleton 這個(gè)類只會(huì)被加載一次,只有類加載的時(shí)候才會(huì)實(shí)例化一個(gè)靜態(tài)變量 UserService 對(duì)象,后續(xù)每次通過 getInstance() 方法都是直接獲取這唯一一個(gè)對(duì)象就可以了,不會(huì)重復(fù)創(chuàng)建對(duì)象。

這就是單例模式的一種寫法,也是企業(yè)開發(fā)中最常用的一種寫法,用了單例模式后,就可以大幅度降低我們創(chuàng)建的對(duì)象數(shù)量,避免堆內(nèi)存頻繁塞滿,頻繁垃圾回收,頻繁 JVM 進(jìn)程停頓影響請(qǐng)求性能,這樣往往可以幫助我們更好的提升系統(tǒng)的性能。

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2024-03-07 12:45:27

PyTorch

2021-02-15 22:07:18

項(xiàng)目策略模式

2010-08-11 09:15:07

設(shè)計(jì)模式Python

2009-07-09 17:30:59

Singleton模式C++ SingletJava Single

2014-03-11 10:03:25

設(shè)計(jì)模式

2011-11-17 16:03:05

Java工廠模式Clojure

2024-09-14 08:24:44

設(shè)計(jì)模式抽象工廠模式JDK

2015-11-03 09:43:43

avascript設(shè)計(jì)模式工廠模式

2022-11-02 08:46:42

Go設(shè)計(jì)模式流程

2012-05-09 10:09:18

JavaMEJava

2021-02-01 10:01:58

設(shè)計(jì)模式 Java單例模式

2019-07-15 13:47:42

Java設(shè)計(jì)模式模式

2023-11-02 21:11:11

JavaScript設(shè)計(jì)模式

2021-03-06 22:50:58

設(shè)計(jì)模式抽象

2022-01-12 13:33:25

工廠模式設(shè)計(jì)

2023-05-04 08:47:31

命令模式抽象接口

2009-08-31 16:01:31

C#和設(shè)計(jì)模式

2013-11-26 16:09:34

Android設(shè)計(jì)模式

2020-10-23 09:40:26

設(shè)計(jì)模式

2020-11-03 13:05:18

命令模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)