複製鏈接
請複製以下鏈接發送給好友

多線程

鎖定
多線程(multithreading),是指從軟件或者硬件上實現多個線程併發執行的技術。具有多線程能力的計算機因有硬件支持而能夠在同一時間執行多於一個線程,進而提升整體處理性能。具有這種能力的系統包括對稱多處理機多核心處理器以及芯片級多處理同時多線程處理器。在一個程序中,這些獨立運行的程序片段叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理” [1] 
中文名
多線程
外文名
multithreading
用    途
實現多個線程併發執行的技術
對    象
計算機
含    義
軟件或者硬件上實現多個線程併發執行的技術
作    用
提升整體處理性能

多線程簡介

多線程是並行化的一種形式,或者是拆分工作以便同時進行處理。線程化的程序將工作拆分到多個軟件線程,而不是將大量工作交給單個內核。這些線程由不同的 CPU 內核並行處理,以節省時間。 [10] 
根據其構建方式,遊戲可能是輕線程的,也可能是重線程的。一些舊遊戲引擎以依賴單線程性能而聞名,這意味着它們大多使用單個 CPU 內核,並通過更高的時鐘速度來獲得大幅度性能提升。 [10] 
如今,Unreal Engine 4 等遊戲引擎都會在創建複雜場景時利用多個內核。引擎還可以使用多線程來處理“繪製調用”( CPU 向 GPU 發送的關於繪製遊戲內對象、紋理和着色器的指令)的不同部分。 [10] 
在計算機編程中,一個基本的理念就是同時對多個任務加以控制。許多程序設計問題都要求程序能夠停下手頭的工作,改為處理其他一些問題,再返回主進程,也就是“中斷”。可以通過多種途徑和方式達到中斷的目的。最早,掌握計算機低級編程語言的程序員編寫的一些“中斷服務例程”,其中主進程的暫停是通過硬件級的中斷實現的。儘管這是一種有用的方法,但編出的程序很難移植,由此造成了另一類的代價高昂問題。中斷對那些實時性很強的任務來説是很有必要的。但對於其他許多問題,只要求將問題劃分進入獨立運行的程序片段中,使整個程序能更迅速地響應用户的請求 [2] 
原本,線程只是用於分配單個處理器的處理時間的一種工具。但假如操作系統本身支持多個處理器,那麼每個線程都可分配給一個不同的處理器,真正進入“並行運算”狀態。從程序設計語言的角度看,多線程操作最有價值的特性之一就是程序員不必關心到底使用了多少個處理器。程序在邏輯意義上被分割為數個線程;假如機器本身安裝了多個物理處理器或邏輯處理器,那麼程序會運行得更快,無需作出任何特殊的調校。根據前面的論述,大家可能感覺多線程處理有利無弊,但必須注意一個問題:共享資源。如果有多個線程同時運行,當它們試圖訪問相同的資源,就會遇到問題。舉個例子來説,兩個線程不能將信息同時發送給一台打印機。為解決這個問題,對那些可共享的資源來説(比如打印機),它們在使用期間必須進入鎖定狀態。所以一個線程可將資源鎖定,在完成了它的任務後,再解開(釋放)這個鎖,使其他線程可以接着使用同樣的資源 [2] 
線程是進程中的一部分,也是進程的的實際運作單位,它也是操作系統中的最小運算調度單位。進程中的一個單一順序的控制流就是一條線程,多個線程可以在一個進程中併發。可以使用多線程技術來提高運行效率 [8] 
多線程是為了同步完成多項任務,不是為了提高運行效率,而是為了提高資源使用效率來提高系統的效率。線程是在同一時間需要完成多項任務的時候實現的 [2] 

多線程原理

實現多線程是採用一種併發執行機制 [3] 
併發執行機制原理:簡單地説就是把一個處理器劃分為若干個短的時間片,每個時間片依次輪流地執行處理各個應用程序,由於一個時間片很短,相對於一個應用程序來説,就好像是處理器在為自己單獨服務一樣,從而達到多個應用程序在同時進行的效果 [3] 
多線程就是把操作系統中的這種併發執行機制原理運用在一個程序中,把一個程序劃分為若干個子任務,多個子任務併發執行,每一個任務就是一個線程。這就是多線程程序 [3] 
多線程技術不但可以提高交互速度,而且能夠更加高效、便捷地進行控制。在對多線程應用的時候,可以使程序響應速度得到提高,從而實現速度化、高效化的特點。另外,多線程技術存在的缺點也比較明顯,需要等待比較長的時間之外,還會在一定程度上使程序運行速度降低,使工作效率受到一定的影響,從而對資源造成了浪費。 [9] 

多線程優點

1、使用線程可以把佔據時間長的程序中的任務放到後台去處理 [4] 
2、用户界面可以更加吸引人,這樣比如用户點擊了一個按鈕去觸發某些事件的處理,可以彈出一個進度條來顯示處理的進度 [4] 
3、程序的運行速度可能加快 [4] 
4、在一些等待的任務實現上如用户輸入、文件讀寫和網絡收發數據等,線程就比較有用了。在這種情況下可以釋放一些珍貴的資源如內存佔用等 [4] 
5、多線程技術iOS軟件開發中也有舉足輕重的作用 [4] 

多線程缺點

1、如果有大量的線程,會影響性能,因為操作系統需要在它們之間切換 [4] 
2、更多的線程需要更多的內存空間 [4] 
3、線程可能會給程序帶來更多“bug”,因此要小心使用 [4] 
4、線程的中止需要考慮其對程序運行的影響 [4] 
5、通常塊模型數據是在多個線程間共享的,需要防止線程死鎖情況的發生 [4] 

多線程優勢

多進程程序結構和多線程程序結構有很大的不同,多線程程序結構相對於多進程程序結構有以下的優勢: [5] 
1、方便的通信和數據交換
線程間有方便的通信和數據交換機制。對於不同進程來説,它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由於同一進程下的線程之間共享數據空間,所以一個線程的數據可以直接為其他線程所用,這不僅快捷,而且方便 [5] 
2、更高效地利用CPU
使用多線程可以加快應用程序的響應。這對圖形界面的程序尤其有意義,當一個操作耗時很長時,整個系統都會等待這個操作,此時程序不會響應鍵盤、鼠標、菜單的操作,而使用多線程技術,將耗時長的操作置於一個新的線程,就可以避免這種尷尬的情況 [5] 
同時,多線程使多CPU系統更加有效。操作系統會保證當線程數不大於CPU數目時,不同的線程運行於不同的CPU上 [5] 

多線程概念區分

線程與多線程
線程是系統對代碼的執行進程,如果將系統當作一個員工,被安排執行某個任務的時候,他不會對任何其他的任務作出響應。只有當這個任務執行完畢,才可以重新給他分配任務。一個程序都有一個主線程,負責執行程序必要的任務 [6] 
當我們處理一個消耗大的任務(如上傳或下載圖片),如果讓主線程執行這個任務,它會等到動作完成,才繼續後面的代碼。在這段時間之內,主線程處於“忙碌”狀態,也就是無法執行任何其他功能。體現在界面上就是,用户的界面完全“卡死” [6] 
多線程是指,將原本線性執行的任務分開成若干個子任務同步執行,這樣做的優點是防止線程“堵塞”,增強用户體驗和程序的效率。缺點是代碼的複雜程度會大大提高,而且對於硬件的要求也相應地提高 [6] 

多線程應用

至2024年,世界上大多數計算機仍然採用的是馮·諾依曼結構,這種結構的特點就是順序處理,一個處理器在同個時刻只能處理一件事情。 Windows 95/NT採用一種全新的任務調度策略,它把一個進程劃分為多個線程,每個線程輪流佔用CPU的運算時間,操作系統不斷地把線程掛起、喚醒、再掛起、再喚醒,如此反覆,由於CPU的速度比較快,給人的感覺是多個線程在同時執行,就好像有多個CPU存在於計算機中一樣 [7] 
多線程的一個典型例子是:用資源管理器複製文件時,一方面在進行磁盤讀寫操作,同時一張紙不停地從一個文件夾飄到另一個文件夾,這個飄的動作實際上是一段視頻剪輯,也就是説,資源管理器能夠同時進行磁盤讀寫和播放視頻剪輯 [7] 

多線程多線程代碼實現

public class SimpleThread {
    //私有的靜態成員內部類,實現了Runnable接口
    private static class ThreadMessage implements Runnable{
        public void run(){
            String[] info = {"消息1","消息2", "消息3", "消息4"};
            try {
                for(int i=0;i<info.length;i++){
                    Thread.sleep(4000);
                    displayThreadMessage(info[i]);
                }
            } catch (InterruptedException e) {
                        displayThreadMessage("不能正常工作");
            }
        }
    }
    //顯示消息,消息是當前線程的名字
    static void displayThreadMessage(String message){
        String threadName = Thread.currentThread().getName();
        //格式化輸出線程消息
        System.out.format("%s: %s%n", threadName, message);
    }
    public static void main(String[] args) throws InterruptedException {
        // 中斷ThreadMessage線程之前延遲的毫秒數(默認是一分鐘)
            long delay =1000 * 60;
        //如果有命令行參數,那麼在命令行參數中給出推遲的時間
            if(args.length>0){
                try {
                    delay =Long.parseLong(args[0])*1000;
                } catch (NumberFormatException e) {
                    System.err.println("參數必須是整數");
                    System.exit(1);
                }
            }
        displayThreadMessage("啓動線程ThreadMessage...");
        long startTime = System.currentTimeMillis();
        Thread t = new Thread(new ThreadMessage());
            t.start();
        displayThreadMessage("等待線程ThreadMessage結束...");
            //循環直到ThreadMessage線程退出
            while(t.isAlive()){
                displayThreadMessage("繼續等待線程ThreadMessage...");
                //最多等待3秒鐘ThreadMessage線程結束
                t.join(3000);
                //如果線程t運行的時間超過delay指定時間
                if(((System.currentTimeMillis() - startTime) > delay) && t.isAlive()){
                    displayThreadMessage("線程ThreadMessage運行時間太久了,不想等待!");
                    t.interrupt();
                    t.join();
                }
            }
        displayThreadMessage("結束線程ThreadMessage!!!");
    }
}
參考資料
  • 1.    謝箭,何小羣,LABVIEW實用程序設計,西南交通大學出版社,2017.07,第125頁
  • 2.    楊成興等編著,電力系統IT應用1000問,中國電力出版社,2010.10,第66頁
  • 3.    邢靜宇主編,Java語言程序設計,吉林大學出版社,2015.01,第244頁
  • 4.    胡璞編著,體育裝備嵌入式技術,中國地質大學出版社,2014.09,第259頁
  • 5.    周立功主編,嵌入式Linux開發教程 上,北京航空航天大學出版社,2016.03,第312頁-第313頁
  • 6.    睿峯科技編,蘋果iOS 6開發從入門到實戰,當代中國出版社,2013.06,第251頁
  • 7.    徐新華編著,C++ Builder 3編程指南,人民郵電出版社,1998.11,第489頁
  • 8.    朱倩.多線程技術在Java中的應用[J].福建電腦,2021,37(9):108-110
  • 9.    韓曉豔,袁堂青.探討Java多線程下載技術[J].電腦知識與技術:學術版,2019,15(8):71-72
  • 10.    什麼是超線程?  .Intel官網[引用日期2023-09-28]