-
多線程
鎖定
多線程簡介
如今,Unreal Engine 4 等遊戲引擎都會在創建複雜場景時利用多個內核。引擎還可以使用多線程來處理“繪製調用”( CPU 向 GPU 發送的關於繪製遊戲內對象、紋理和着色器的指令)的不同部分。
[10]
在計算機編程中,一個基本的理念就是同時對多個任務加以控制。許多程序設計問題都要求程序能夠停下手頭的工作,改為處理其他一些問題,再返回主進程,也就是“中斷”。可以通過多種途徑和方式達到中斷的目的。最早,掌握計算機低級編程語言的程序員編寫的一些“中斷服務例程”,其中主進程的暫停是通過硬件級的中斷實現的。儘管這是一種有用的方法,但編出的程序很難移植,由此造成了另一類的代價高昂問題。中斷對那些實時性很強的任務來説是很有必要的。但對於其他許多問題,只要求將問題劃分進入獨立運行的程序片段中,使整個程序能更迅速地響應用户的請求
[2]
。
原本,線程只是用於分配單個處理器的處理時間的一種工具。但假如操作系統本身支持多個處理器,那麼每個線程都可分配給一個不同的處理器,真正進入“並行運算”狀態。從程序設計語言的角度看,多線程操作最有價值的特性之一就是程序員不必關心到底使用了多少個處理器。程序在邏輯意義上被分割為數個線程;假如機器本身安裝了多個物理處理器或邏輯處理器,那麼程序會運行得更快,無需作出任何特殊的調校。根據前面的論述,大家可能感覺多線程處理有利無弊,但必須注意一個問題:共享資源。如果有多個線程同時運行,當它們試圖訪問相同的資源,就會遇到問題。舉個例子來説,兩個線程不能將信息同時發送給一台打印機。為解決這個問題,對那些可共享的資源來説(比如打印機),它們在使用期間必須進入鎖定狀態。所以一個線程可將資源鎖定,在完成了它的任務後,再解開(釋放)這個鎖,使其他線程可以接着使用同樣的資源
[2]
。
多線程原理
併發執行機制原理:簡單地説就是把一個處理器劃分為若干個短的時間片,每個時間片依次輪流地執行處理各個應用程序,由於一個時間片很短,相對於一個應用程序來説,就好像是處理器在為自己單獨服務一樣,從而達到多個應用程序在同時進行的效果
[3]
。
多線程技術不但可以提高交互速度,而且能夠更加高效、便捷地進行控制。在對多線程應用的時候,可以使程序響應速度得到提高,從而實現速度化、高效化的特點。另外,多線程技術存在的缺點也比較明顯,需要等待比較長的時間之外,還會在一定程度上使程序運行速度降低,使工作效率受到一定的影響,從而對資源造成了浪費。
[9]
多線程優點
多線程缺點
多線程優勢
1、方便的通信和數據交換
線程間有方便的通信和數據交換機制。對於不同進程來説,它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由於同一進程下的線程之間共享數據空間,所以一個線程的數據可以直接為其他線程所用,這不僅快捷,而且方便
[5]
。
2、更高效地利用CPU
使用多線程可以加快應用程序的響應。這對圖形界面的程序尤其有意義,當一個操作耗時很長時,整個系統都會等待這個操作,此時程序不會響應鍵盤、鼠標、菜單的操作,而使用多線程技術,將耗時長的操作置於一個新的線程,就可以避免這種尷尬的情況
[5]
。
多線程概念區分
線程與多線程
線程是系統對代碼的執行進程,如果將系統當作一個員工,被安排執行某個任務的時候,他不會對任何其他的任務作出響應。只有當這個任務執行完畢,才可以重新給他分配任務。每一個程序都有一個主線程,負責執行程序必要的任務
[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]