偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一篇學會Java多線程之線程

開發(fā) 后端
我們在學習軟件開發(fā)時,多線程,高并發(fā)是一個必不可少的知識點,也是在面試時必會問到的內(nèi)容,為了讓大家對多線程,高并發(fā)編程有個清晰認識,特地組織了一個專欄來專門介紹一下,希望能對大家有一些幫助。

本文轉載自微信公眾號「我是開發(fā)者FTD」,作者FTD。轉載本文請聯(lián)系我是開發(fā)者FTD公眾號。

我們在學習軟件開發(fā)時,多線程,高并發(fā)是一個必不可少的知識點,也是在面試時必會問到的內(nèi)容,為了讓大家對多線程,高并發(fā)編程有個清晰認識,特地組織了一個專欄來專門介紹一下,希望能對大家有一些幫助。

線程簡介

線程是程序運行的基本執(zhí)行單元。當操作系統(tǒng)(不包括單線程的操作系統(tǒng),如微軟早期的DOS)在執(zhí)行一個程序時,會在系統(tǒng)中建立一個進程,而在這個進程中,必須至少建立一個線程(這個線程被稱為主線程)來作為這個程序運行的入口點。因此,在操作系統(tǒng)中運行的任何程序都至少有一個主線程。

進程和線程是現(xiàn)代操作系統(tǒng)中兩個必不可少的運行模型。在操作系統(tǒng)中可以有多個進程,這些進程包括系統(tǒng)進程(由操作系統(tǒng)內(nèi)部建立的進程)和用戶進程(由用戶程序建立的進程);一個進程中可以有一個或多個線程。進程和進程之間不共享內(nèi)存,也就是說系統(tǒng)中的進程是在各自獨立的內(nèi)存空間中運行的。而一個進程中的線可以共享系統(tǒng)分派給這個進程的內(nèi)存空間。

在進一步介紹之前,我們先來了解一些基本概念,以幫助大家更快速的理解。

基本概念

進程

進程是操作系統(tǒng)中正在執(zhí)行的不同的應用程序,例如:我們可以同時打開微信和QQ,甚至更多的程序。

在操作系統(tǒng)中運行的程序就是進程,進程就是執(zhí)行程序的一次執(zhí)行過程,它是一個動態(tài)的概念式系統(tǒng)資源分配的單位

通常在一個進程中可以包含若干個線程,當然一個進程中至少有一個線程,不然沒有存在的意義,線程是CPU調(diào)度和執(zhí)行的單位

線程

線程是一個應用程序進程中不同的執(zhí)行路徑,例如:我們的WEB服務器,能夠為多個用戶同時提供請求服務。

進程是不活潑的,進程從來不執(zhí)行任何東西,它只是線程的容器。線程總是在某個進程環(huán)境中創(chuàng)建的,而且它的整個生命周期都在該進程中。

在一個進程中,如果創(chuàng)建了多個線程,線程的運行是由調(diào)度器安排調(diào)度的,調(diào)度器是與操作系統(tǒng)緊密相關的,先后順序是不能人為干預的

多線程

多線程擁有多條執(zhí)行路徑,「主線程與子線程并行交替執(zhí)行」(普通方法只有主線程一條路徑),對同一份資源操作時,會存在資源搶奪的問題,這時就需要加入并發(fā)控制了。

一個Java應用程序,至少有三個線程: main()主線程, gc()垃圾回收線程,異常處理線程。當然如果發(fā)生異常,會影響主線程。

多線程程序的優(yōu)點:

  • 提高應用程序的響應。對圖形化界面更有意義,可增強用戶體驗。同時做多個事情。比如:一邊聽歌、一邊寫代碼。
  • 提高計算機系統(tǒng)CPU的利用率。不過線程也會帶來額外的開銷,如CPU調(diào)度時間,并發(fā)控制帶來的系統(tǒng)開銷。
  • 改善程序結構。將既長又復雜的進程分為多個線程,獨立運行,利于理解和修改。

何時需要多線程?

程序需要同時執(zhí)行兩個或多個任務。

需要一些后臺運行的程序時,比如:Java后臺運行的GC線程。

創(chuàng)建線程

Java中創(chuàng)建線程有四種方式,我們下面依次介紹一下。

1、繼承 Thread 類

(1)定義Thread類的子類,并重寫該類的run方法,該run方法的方法體就代表了線程要完成的任務。因此把run()方法稱為執(zhí)行體。

(2)創(chuàng)建Thread子類的實例對象,即創(chuàng)建了一個線程對象。

(3)調(diào)用該線程對象的start()方法來啟動該線程。

示例代碼:

  1. public class MyThread extends Thread { 
  2.  
  3.     // 總票數(shù) 
  4.     public int count = 10; 
  5.  
  6.     @Override 
  7.     public void run() { 
  8.         // 當還有票時就繼續(xù)售賣 
  9.         while (count > 0) { 
  10.             // 剩余票數(shù) 
  11.             count--; 
  12.             System.out.println( 
  13.                     Thread.currentThread().getName() + "售賣第 " + (10 - count) + " 張票,當前剩余票數(shù): " + count); 
  14.         } 
  15.     } 
  16.  
  17.     public static void main(String[] args) { 
  18.         MyThread myThread = new MyThread(); 
  19.         myThread.start(); 
  20.     } 

2、實現(xiàn)Runnable接口

(1)定義Runnable接口的實現(xiàn)類,并重寫該接口的run()方法,該run()方法的方法體同樣是該線程的線程執(zhí)行體。

(2)創(chuàng)建 Runnable實現(xiàn)類的實例對象,并將該實例作為Thread的target來創(chuàng)建一個Thread對象,該Thread對象才是真正的線程運行對象。

(3)調(diào)用該線程對象的start()方法來啟動線程。

示例代碼:

  1. public class MyRunableThread implements Runnable { 
  2.  
  3.     // 總票數(shù) 
  4.     public int count = 10; 
  5.  
  6.     @Override 
  7.     public void run() { 
  8.         // 當還有票時就繼續(xù)售賣 
  9.         while (count > 0) { 
  10.             // 剩余票數(shù) 
  11.             count--; 
  12.             System.out.println( 
  13.                     Thread.currentThread().getName() + "售賣第 " + (10 - count) + " 張票,當前剩余票數(shù): " + count); 
  14.         } 
  15.     } 
  16.  
  17.     public static void main(String[] args) { 
  18.         MyRunableThread myRunableThread = new MyRunableThread(); 
  19.         Thread myThread = new Thread(myRunableThread); 
  20.         myThread.start(); 
  21.     } 

「Thread 和 Runnable 的區(qū)別」

上述兩種方法是大家最常見到的兩種創(chuàng)建線程的方法,也常常會被問到兩種方式創(chuàng)建線程的區(qū)別,下面簡單總結了一下:

「繼承 Thread 類」

子類繼承 Thread 類具備多線程能力

啟動線程:子類線程對象調(diào)用 .start()方法

不建議使用:避免 OOP 單繼承局限性

「實現(xiàn)接口 Runnable」

  • 具有多線程能力
  • 啟動線程:傳入目標對象 + Thread對象調(diào)用.start()方法
  • 推薦使用:避免單繼承局限性,方便同一個對象被多個線程使用

另外,在使用線程池時只能放入實現(xiàn)Runable或Callable類線程,不能直接放入繼承Thread的類

3、實現(xiàn)Callable接口

(1)創(chuàng)建Callable接口的實現(xiàn)類,并實現(xiàn)call()方法,該call()方法將作為線程執(zhí)行體,并且有返回值。

(2)創(chuàng)建Callable實現(xiàn)類的實例,使用FutureTask類來包裝Callable對象,該FutureTask對象封裝了該Callable對象的call()方法的返回值。

(3)使用FutureTask對象作為Thread對象的target創(chuàng)建并啟動新線程。

(4)調(diào)用FutureTask對象的get()方法來獲得子線程執(zhí)行結束后的返回值。

示例代碼:

  1. public class MyCallableThread implements Callable<String> { 
  2.  
  3.     // 總票數(shù) 
  4.     private int count = 10; 
  5.  
  6.     @Override 
  7.     public String call() throws Exception { 
  8.         // 當還有票時就繼續(xù)售賣 
  9.         while (count > 0) { 
  10.             // 剩余票數(shù) 
  11.             count--; 
  12.             System.out.println( 
  13.                     Thread.currentThread().getName() + "售賣第 " + (10 - count) + " 張票,當前剩余票數(shù): " + count); 
  14.         } 
  15.         return "票已售完"
  16.     } 
  17.  
  18.     public static void main(String[] args) throws InterruptedException, ExecutionException { 
  19.         Callable<String> callable = new MyCallableThread(); 
  20.         FutureTask<String> futureTask = new FutureTask<>(callable); 
  21.         Thread myThread = new Thread(futureTask); 
  22.         myThread.start(); 
  23.         // 打印返回結果 
  24.         System.out.println(futureTask.get()); 
  25.     } 

「Runnable和Callable的區(qū)別:」

Callable規(guī)定的方法是call(),Runnable規(guī)定的方法是run()。

Callable的任務執(zhí)行后可返回值,而Runnable的任務是不能有返回值。

call方法可以拋出異常,run方法不可以。

4、線程池

Java默認提供了五種線程池,通過Executors創(chuàng)建,分別為:

  • 「newCachedThreadPool」 創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
  • 「newFixedThreadPool」 創(chuàng)建一個定長線程池,可控制線程最大并發(fā)數(shù),超出的線程會在隊列中等待。
  • 「newScheduledThreadPool」 創(chuàng)建一個定長線程池,支持定時及周期性任務執(zhí)行。
  • 「newSingleThreadExecutor」 創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務,保證所有任務按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行。
  • 「newWorkStealingPool」 創(chuàng)建一個具有搶占式操作的線程池,由于能夠合理的使用CPU進行對任務操作(并行操作),所以適合使用在很耗時的任務中。

示例代碼:

  1. public class MyThreadPool implements Runnable { 
  2.  
  3.     // 總票數(shù) 
  4.     public int count = 10; 
  5.  
  6.     @Override 
  7.     public void run() { 
  8.         // 當還有票時就繼續(xù)售賣 
  9.         while (count > 0) { 
  10.             // 剩余票數(shù) 
  11.             count--; 
  12.             System.out.println( 
  13.                     Thread.currentThread().getName() + "售賣第 " + (10 - count) + " 張票,當前剩余票數(shù): " + count); 
  14.         } 
  15.     } 
  16.  
  17.     public static void main(String[] args) { 
  18.         ExecutorService ex = Executors.newFixedThreadPool(5); 
  19.         MyThreadPool t = new MyThreadPool(); 
  20.         ex.submit(t); 
  21.         ex.shutdown(); 
  22.     } 

關于線程池,后續(xù)會有單獨文章給大家詳細介紹。

 

通過以上的內(nèi)容,希望大家可以對線程有個初步的認識,相關示例代碼,稍后整理后我會上傳到GitHub上,也請大家留意我們的后續(xù)文章。

 

責任編輯:武曉燕 來源: 我是開發(fā)者FTD
相關推薦

2021-12-26 18:22:30

Java線程多線程

2021-02-25 15:58:46

C++線程編程開發(fā)技術

2021-12-28 09:10:55

Java線程狀態(tài)

2019-09-24 14:19:12

PythonC語言文章

2021-03-28 09:12:58

多線程死鎖技術熱點

2021-06-26 16:05:15

內(nèi)核線程運行

2021-02-15 13:38:38

多線程異步模型

2010-03-16 17:16:38

Java多線程

2010-01-21 11:25:44

linux多線程線程資源

2011-06-22 16:08:40

Qt 多線程 事件循環(huán)

2022-01-02 08:43:46

Python

2023-01-28 09:50:17

java多線程代碼

2022-03-14 08:16:00

Java程序開發(fā)

2021-11-30 19:58:51

Java問題排查

2021-03-05 07:38:52

C++線程編程開發(fā)技術

2016-04-12 09:48:24

nsthread多線程ios

2011-06-22 16:02:37

Qt 多線程 重入

2017-05-27 20:59:30

Java多線程synchronize

2021-07-02 09:45:29

MySQL InnoDB數(shù)據(jù)

2021-07-06 08:59:18

抽象工廠模式
點贊
收藏

51CTO技術棧公眾號