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

用好單例設(shè)計模式,代碼性能提升300%

開發(fā) 后端
今天給大家分享一個寫代碼的設(shè)計模式,就是我們最最耳熟能詳?shù)膯卫O(shè)計模式。

目錄

  • 一次請求執(zhí)行流程。
  • java 代碼是如何運行的?
  • 堆內(nèi)存滿了后怎么辦?
  • 用單例模式如何優(yōu)化系統(tǒng)性能呢?

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

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

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

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

平時創(chuàng)建對象這個簡單吧,比如我們搞一個對外的 web 接口,然后再接口收到一個請求的時候,就創(chuàng)建一個對象。

這個偽代碼如下:

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

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

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

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

但是這里有一個問題,大家知道每次處理請求的時候,這段代碼運行他會干什么事情嗎?

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

java 代碼是如何運行的?

下面就得給大家來揭秘一下這個代碼運行的底層原理了,首先呢,當我們啟動一個 Java 程序的時候,一定會啟動一個 JVM 進程。

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

如果你是直接運行 main 方法來啟動的,那么就會直接啟動一個 JVM 進程,如果你是把代碼打包以后放 Tomcat 里運行的,那么 Tomcat 自己本身就是一個 JVM 進程。

如下圖:

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

如下圖所示:

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

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

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

如下圖:

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

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

如下圖:

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

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

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

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

如下圖:

但是每次垃圾回收都有一個問題,他因為要清理掉一些對象,所以往往會在清理對象的時候,避免你再創(chuàng)建新的對象了。

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

如下圖:

那么在垃圾回收進行中,JVM 進程停止運行的這個期間,是不是會導致一個問題,那就是你的用戶發(fā)送過來的請求就沒人處理了。

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

如下圖:

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

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

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

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

讓一個對象就創(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;
}
}

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

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

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

責任編輯:姜華 來源: 石杉的架構(gòu)筆記
相關(guān)推薦

2021-02-01 10:01:58

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

2021-03-02 08:50:31

設(shè)計單例模式

2013-11-26 16:20:26

Android設(shè)計模式

2016-03-28 10:23:11

Android設(shè)計單例

2022-06-07 08:55:04

Golang單例模式語言

2022-02-06 22:30:36

前端設(shè)計模式

2024-02-04 12:04:17

2015-09-06 11:07:52

C++設(shè)計模式單例模式

2021-08-11 17:22:11

設(shè)計模式單例

2022-09-29 08:39:37

架構(gòu)

2021-09-07 10:44:35

異步單例模式

2015-01-14 13:26:58

AndroidJava單例

2023-03-21 15:21:52

開發(fā)程序設(shè)計static

2021-02-07 23:58:10

單例模式對象

2011-03-16 10:13:31

java單例模式

2021-01-04 09:43:24

Python 開發(fā)編程語言

2022-10-30 17:32:25

設(shè)計模式單例模式

2023-08-03 08:01:27

單例模式結(jié)構(gòu)開發(fā)

2023-07-31 12:27:30

單例設(shè)計模式

2023-09-19 10:31:09

算法數(shù)據(jù)
點贊
收藏

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