國(guó)內(nèi)免費(fèi)二級(jí)域名網(wǎng)站做電商如何起步
定義
1、進(jìn)程:進(jìn)程是一個(gè)具有獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的以此運(yùn)行活動(dòng)。 是系統(tǒng)進(jìn)行資源分配和調(diào)度的獨(dú)立單位,也是基本的執(zhí)行單元。是一個(gè)動(dòng)態(tài)的概念,是一個(gè)活動(dòng)的實(shí)體。它不只是程序的代碼,還包括當(dāng)前的活動(dòng)。
進(jìn)程結(jié)構(gòu)特征: 由程序、數(shù)據(jù)和進(jìn)程控制塊三部分組成。具有 獨(dú)立性、并發(fā)性、異步性和動(dòng)態(tài)性的特點(diǎn)。
(1)、進(jìn)程的概念主要有兩點(diǎn):
第一,進(jìn)程是一個(gè)實(shí)體。每一個(gè)進(jìn)程都有它自己的地址空間,一般情況下,包括
文本區(qū)域(text region)--存儲(chǔ)處理器執(zhí)行的代碼,
數(shù)據(jù)區(qū)域(data region)--存儲(chǔ)程序執(zhí)行期間的一些數(shù)據(jù)變量,
堆棧(stack region)--存儲(chǔ)動(dòng)態(tài)分配的內(nèi)存和本地變量及指令。
第二:進(jìn)程是一個(gè)“執(zhí)行中的程序”。程序是一個(gè)沒(méi)有生命的實(shí)體,只有在運(yùn)行時(shí)處理器才會(huì)賦予它生命,才能成為一個(gè)活動(dòng)的實(shí)體,我們稱其為“進(jìn)程”。
每一個(gè)進(jìn)程都會(huì)有一個(gè)獨(dú)一無(wú)二的編號(hào),被稱為進(jìn)程標(biāo)識(shí)碼,簡(jiǎn)稱PID(Process,identifier),它是一個(gè)取值為1-32768.但是init是一個(gè)特殊的進(jìn)程。所謂的init進(jìn)程,是一個(gè)內(nèi)核啟動(dòng)的用戶級(jí)進(jìn)程,也是系統(tǒng)上運(yùn)行的所有其他進(jìn)程的父進(jìn)程,他會(huì)觀察子進(jìn)程,并在需要的時(shí)候啟動(dòng),停止,重新啟動(dòng)它們,init進(jìn)程主要完成系統(tǒng)各項(xiàng)的配置。linux系統(tǒng)中,init從根文件夾系統(tǒng)目錄里的/etc/inittab文件里獲取信息。是所有進(jìn)程的發(fā)起者和控制者,內(nèi)核啟動(dòng)后,便由init進(jìn)程來(lái)進(jìn)行各項(xiàng)配置。
(2)、進(jìn)程的三種狀態(tài):
就緒(Ready)狀態(tài):當(dāng)進(jìn)程分配到除CPU以外的必要資源后,只要再獲得CPU,便可以立即執(zhí)行,進(jìn)程這時(shí)的狀態(tài)為就緒狀態(tài)。在一個(gè)系統(tǒng)中處于就緒狀態(tài)的進(jìn)程可能有多個(gè),通常將它們排成一個(gè)隊(duì)列,稱為就緒隊(duì)列。
阻塞(Blocked)狀態(tài):正在執(zhí)行的進(jìn)程由于發(fā)生某事件或接受某消息無(wú)法繼續(xù)執(zhí)行時(shí),便放棄處理機(jī)而處于暫停狀態(tài),也即進(jìn)程的執(zhí)行收到阻塞,把這種暫停狀態(tài)稱為阻塞狀態(tài),有時(shí)也稱為等待狀態(tài)和封鎖狀態(tài)。通常使進(jìn)程處于阻塞的原因有:請(qǐng)求I/O,申請(qǐng)緩沖空間。也會(huì)產(chǎn)生一個(gè)相應(yīng)的阻塞隊(duì)列。
運(yùn)行(Running)狀態(tài):進(jìn)程已獲得CPU,其程序正在執(zhí)行。在單處理機(jī)系統(tǒng)中,只有一個(gè)進(jìn)程處于執(zhí)行狀態(tài),在多處理機(jī)系統(tǒng)中,則有多個(gè)進(jìn)程處于執(zhí)行狀態(tài);
其關(guān)系如下圖所示:
2、線程:線程是進(jìn)程中的執(zhí)行運(yùn)算的最小單位,是進(jìn)程中的一個(gè)實(shí)體,是被系統(tǒng)獨(dú)立調(diào)度和分派的基本單位,線程自己不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源( 程序計(jì)數(shù)器,一組寄存器和棧),但它可與同屬一個(gè)進(jìn)程的其他線程 共享進(jìn)程所擁有的全部資源。
線程優(yōu)點(diǎn):
- (1)易于調(diào)度。
- (2)提高并發(fā)性。通過(guò)線程可方便有效地實(shí)現(xiàn)并發(fā)性。進(jìn)程可創(chuàng)建多個(gè)線程來(lái)執(zhí)行同一個(gè)程序的不同部分。
- (3)開(kāi)銷(xiāo)少。創(chuàng)建線程比創(chuàng)建進(jìn)程要快,所需開(kāi)銷(xiāo)少,占用的資源也少;
- (4)充分發(fā)揮多處理器的功能。通過(guò)創(chuàng)建多線程進(jìn)程,每個(gè)線程在一個(gè)處理器上運(yùn)行,從而實(shí)現(xiàn)應(yīng)用程序的并發(fā)性,使每個(gè)處理器都得到充分的運(yùn)行。
二、進(jìn)程與線程的區(qū)別
(1)調(diào)度:線程作為處理器調(diào)度和分配的基本單位,而進(jìn)程是作為擁有資源的基本單位
(2)并發(fā)性:不僅進(jìn)程之間可以并發(fā)執(zhí)行,同一個(gè)進(jìn)程的多個(gè)線程之間也可以并發(fā)執(zhí)行
(3)擁有資源:進(jìn)程是擁有資源的一個(gè)獨(dú)立單位,有自己獨(dú)立的地址空間;線程不擁有系統(tǒng)資源,但可以訪問(wèn)隸屬于進(jìn)程的資源,共享進(jìn)程的地址空間.
(4)系統(tǒng)開(kāi)銷(xiāo):在創(chuàng)建或撤消進(jìn)程時(shí),由于系統(tǒng)都要為之分配和回收資源,導(dǎo)致系統(tǒng)的開(kāi)銷(xiāo)明顯大于創(chuàng)建或撤消線程時(shí)的開(kāi)銷(xiāo)。
三、進(jìn)程和線程的關(guān)系
(1)二者均可并發(fā)執(zhí)行.
(2)線程是指進(jìn)程內(nèi)的一個(gè)執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體。一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程,一個(gè)線程只屬于一個(gè)進(jìn)程.
(3)資源分配給進(jìn)程,同一進(jìn)程的所有線程共享該進(jìn)程的所有資源。
(4)處理機(jī)分給線程,即真正在處理機(jī)上運(yùn)行的是線程。
(5)線程在執(zhí)行過(guò)程中,需要協(xié)作同步。不同進(jìn)程的線程間要利用消息通信的辦法實(shí)現(xiàn)同步。線程是指進(jìn)程內(nèi)的一個(gè)執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體.進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。 進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響。而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑,線程有自己的堆棧和局部變量,但線程之間沒(méi)有單獨(dú)的地址空間, 一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時(shí),耗費(fèi)資源較大,效率要差一些。但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)程。
四、進(jìn)程間通信的方式
(1)管道(pipe)及有名管道(named pipe):管道可用于具有親緣關(guān)系的父子進(jìn)程間的通信,有名管道除了具有管道所具有的功能外,它還允許無(wú)親緣關(guān)系進(jìn)程間的通信。
(2)信號(hào)(signal):信號(hào)是在軟件層次上對(duì)中斷機(jī)制的一種模擬,它是比較復(fù)雜的通信方式,用于通知進(jìn)程有某事件發(fā)生,一個(gè)進(jìn)程收到一個(gè)信號(hào)與處理器收到一個(gè)中斷請(qǐng)求效果上可以說(shuō)是一致的。
(3)消息隊(duì)列(message queue):消息隊(duì)列是消息的鏈接表,它克服了上兩種通信方式中信號(hào)量有限的缺點(diǎn),具有寫(xiě)權(quán)限得進(jìn)程可以按照一定得規(guī)則向消息隊(duì)列中添加新信息;對(duì)消息隊(duì)列有讀權(quán)限的進(jìn)程則可以從消息隊(duì)列中讀取信息。
(4)共享內(nèi)存(shared memory):可以說(shuō)這是最有用的進(jìn)程間通信方式。它使得多個(gè)進(jìn)程可以訪問(wèn)同一塊內(nèi)存空間,不同進(jìn)程可以及時(shí)看到對(duì)方進(jìn)程中共享內(nèi)存中數(shù)據(jù)的更新。這種方式需要依靠某種同步操作,如互斥鎖和信號(hào)量等。
(5)信號(hào)量(semaphore):主要作為進(jìn)程之間及同一種進(jìn)程的不同線程之間的同步和互斥手段。
(6)套接字(socket):這是一種更為一般的進(jìn)程間通信機(jī)制,它可用于網(wǎng)絡(luò)中不同機(jī)器之間的進(jìn)程間通信,應(yīng)用非常廣泛。
多線程的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 能適當(dāng)提高程序的執(zhí)行效率
- 能適當(dāng)提高資源的利用率(CPU,內(nèi)存)
- 線程上的任務(wù)執(zhí)行完成后,線程會(huì)自動(dòng)銷(xiāo)毀
缺點(diǎn)
- 開(kāi)啟線程需要占用一定的內(nèi)存空間(默認(rèn)情況下,每一個(gè)線程都占 512 KB)
- 如果開(kāi)啟大量的線程,會(huì)占用大量的內(nèi)存空間,降低程序的性能
- 線程越多,CPU 在調(diào)用線程上的開(kāi)銷(xiāo)就越大
- 程序設(shè)計(jì)更加復(fù)雜,比如線程間的通信、多線程的數(shù)據(jù)共享
多線程使用場(chǎng)景:
場(chǎng)景1:當(dāng)某個(gè)接口響應(yīng)速度很慢的時(shí)候,可以使用多線程提升響應(yīng)速度。前提是這個(gè)接口獲取信息的邏輯互相獨(dú)立,比如首頁(yè)接口,需要獲取列表A,列表B,列表C等,而列表ABC三者之間互相獨(dú)立(也就是不需要獲取到A,就能獲取到B),互相之間沒(méi)有關(guān)系。這種情況就可以使用多線程去優(yōu)化,總耗時(shí)為獲取3個(gè)列表當(dāng)中耗時(shí)最長(zhǎng)的那個(gè)。
場(chǎng)景2:多線程分批次處理集合數(shù)據(jù),不處理重復(fù)的數(shù)據(jù)。比如有一張學(xué)生表,數(shù)據(jù)量很大,你需要根據(jù)表當(dāng)中的姓名和身份證號(hào)這兩個(gè)字段去調(diào)用外部接口(外部接口一次只能校驗(yàn)一條數(shù)據(jù)),校驗(yàn)之后還需要更新這張表。這個(gè)時(shí)候可以使用多線程分批次處理,大大提高效率。
public class TestApp {//配置需要同時(shí)開(kāi)啟多少個(gè)線程進(jìn)行處理private final int threadNum = 10;/*** @param list 要處理的集合數(shù)據(jù),如果查詢較慢,可以多線程分批次查詢?nèi)缓髤R總在一塊*/public void handleData(List<User> list) {int size = list.size();if (size == 0 || list == null) {return;}ExecutorService executorService = Executors.newFixedThreadPool(threadNum);List<Future<List<User>>> futures = new ArrayList<Future<List<User>>>(size);for (int i = 0; i < threadNum; i++) {//將數(shù)據(jù)分成threadNum份,線程同時(shí)執(zhí)行int from = size / threadNum * i;int to = size / threadNum * (i + 1);if (i == threadNum - 1) {to = size;}List<User> subList = list.subList(from, to);Callable<List<User>> task = new Callable<List<User>>() {@Overridepublic List<User> call() {List<User> list1 = new ArrayList<>();//對(duì)每個(gè)線程(線程中的每份數(shù)據(jù))的邏輯操作for (User user : subList) {//調(diào)用外部接口Boolean res = checkNameAndIdCard(user.getName, user.getIdCard);user.setRes(res);list1.add(user);}return list1;}};//添加線程到隊(duì)列futures.add(executorService.submit(task));}//多線程處理后的集合匯總到allList<User> all = new ArrayList<>();for (int i = 0; i < futures.size(); i++) {try {List<User> list1 = futures.get(i).get();all.addAll(list1);} catch (Exception e) {e.printStackTrace();}}//批量更新數(shù)據(jù)庫(kù)executorService.shutdown();}/*** 模擬外部接口*/public Boolean checkNameAndIdCard(String name, String idCard) {return true;}}@Data
class User {private Integer id;private String name;private String idCard;private String res;
}
整體流程:
先把要處理的集合從數(shù)據(jù)庫(kù)全部撈出來(lái)
根據(jù)要開(kāi)的線程數(shù)量對(duì)集合進(jìn)行均分
開(kāi)多線程對(duì)每個(gè)集合進(jìn)行處理,處理后返回結(jié)果
Future.get()會(huì)造成主線程阻塞,也就是當(dāng)所有future都得到結(jié)果后主線程才能繼續(xù)執(zhí)行下去
場(chǎng)景3:做異步。比如頁(yè)面上需要導(dǎo)出excel文件,由于業(yè)務(wù)要求,需要導(dǎo)出全部數(shù)據(jù),導(dǎo)出全部數(shù)據(jù)大概需要10分鐘左右,那如果使用同步的方式,用戶需要在這個(gè)導(dǎo)出頁(yè)面等待10分鐘,不能做其它操作,這樣肯定是不行的。那么可以采用異步,用戶點(diǎn)擊導(dǎo)出,導(dǎo)出接口主線程往數(shù)據(jù)庫(kù)當(dāng)中插入一條導(dǎo)出記錄,開(kāi)個(gè)子線程獲取數(shù)據(jù),寫(xiě)入Excel文件,完成之后更新導(dǎo)出記錄,當(dāng)中,然后主線程直接給用戶返回。這樣用戶點(diǎn)擊導(dǎo)出會(huì)生成一個(gè)導(dǎo)出記錄信息,不用在這里等待,等導(dǎo)出完成,之后可以在導(dǎo)出記錄當(dāng)中進(jìn)行下載。代碼就不貼了。
場(chǎng)景4:監(jiān)聽(tīng)線程,如果某個(gè)線程執(zhí)行時(shí)間過(guò)長(zhǎng)(可能死循環(huán)了),超過(guò)了自定義的時(shí)間,就把該線程干掉,釋放cpu資源
情況1:開(kāi)一個(gè)線程去執(zhí)行這個(gè)任務(wù)
public class MainSingle {public static final ExecutorService pool = Executors.newFixedThreadPool(10);public static void main(String[] args) throws Exception {Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "進(jìn)來(lái)了" + this.hashCode());try {Thread.sleep(7000);} catch (InterruptedException e) {}}};FutureTask futureTask = new FutureTask<>(runnable,null);pool.submit(futureTask);long start = System.currentTimeMillis();// 判斷是否完成,如果沒(méi)完成就是一直循環(huán)判斷while (!futureTask.isDone()) {long now = System.currentTimeMillis();if ((now - start) >= 6000) {//超時(shí)時(shí)間3000毫秒futureTask.cancel(true);System.out.println("線程超時(shí)了,終止");}}pool.shutdown();}}
情況2:開(kāi)多個(gè)線程,哪個(gè)線程死循環(huán),就關(guān)閉哪一個(gè)線程,不影響其它線程
知識(shí)來(lái)源:
【23版面試突擊】進(jìn)程和線程的區(qū)別,使用線程真的能節(jié)省時(shí)間?_嗶哩嗶哩_bilibili
操作系統(tǒng):進(jìn)程與線程之間的區(qū)別及聯(lián)系 - 知乎
多線程使用場(chǎng)景_多線程的應(yīng)用場(chǎng)景_木偶亽~的博客-CSDN博客