多線程編程語言
❶ java多線程程序設計初步入門
在Java語言產生前 傳統的程序設計語言的程序同一時刻只能單任務操作 效率非常低 例如程序往往在接收數據輸入時發生阻塞 只有等到程序獲得數據後才能繼續運行 隨著Internet的迅猛發展 這種狀況越來越不能讓人們忍受 如果網路接收數據阻塞 後台程序就處於等待狀態而不繼續任何操作 而這種阻塞是經常會碰到的 此時CPU資源被白白的閑置起來 如果在後台程序中能夠同時處理多個任務 該多好啊!應Internet技術而生的Java語言解決了這個問題 多線程程序是Java語言的一個很重要的特點 在一個Java程序中 我們可以同時並行運行多個相對獨立的線程 例如 我們如果創建一個線程來進行數據輸入輸出 而創建另一個線程在後台進行其它的數據處理 如果輸入輸出線程在接收數據時阻塞 而處理數據的線程仍然在運行 多線程程序設計大大提高了程序執行效率和處理能力
線程的創建
我們知道Java是面向對象的程序語言 用Java進行程序設計就是設計和使用類 Java為我們提供了線程類Thread來創建線程 創建線程與創建普通鬧梁的類的對象的操作是一樣的 而線程就是Thread類或其子類的實例對象 下面是一個創建啟動一個線程的語句
Thread thread =new Thread(); file://聲明困彎神一個對象實例 即創建一個線程
Thread run(); file://用Thread類中的run()方法啟動線程
從這個例子 我們可以通過Thread()構造方法創建一個線程 並啟動該線程 事實上 啟動線程 也就是啟動線程的run()方法 而Thread類中的run()方法沒有任何操作語句 所以這個線程沒有任何操作 要使線程實現預定功能 必須定義自己的run()方法 Java中通常有兩種方式定義run()方法
通過定義一個Thread類的子類 在該子類中重寫run()方法 Thread子類的實例對象就是一個線程 顯然 該線程汪虧有我們自己設計的線程體run()方法 啟動線程就啟動了子類中重寫的run()方法
通過Runnable介面 在該介面中定義run()方法的介面 所謂介面跟類非常類似 主要用來實現特殊功能 如復雜關系的多重繼承功能 在此 我們定義一個實現Runnable() 介面的類 在該類中定義自己的run()方法 然後以該類的實例對象為參數調用Thread類的構造方法來創建一個線程
線程被實際創建後處於待命狀態 激活(啟動)線程就是啟動線程的run()方法 這是通過調用線程的start()方法來實現的
下面一個例子實踐了如何通過上述兩種方法創建線程並啟動它們
// 通過Thread類的子類創建的線程 class thread extends Thread { file://自定義線程的run()方法 public void run() { System out println( Thread is running… ); } } file://通過Runnable介面創建的另外一個線程 class thread implements Runnable { file://自定義線程的run()方法 public void run() { System out println( Thread is running… ); } } file://程序的主類 class Multi_Thread file://聲明主類 { plubic static void mail(String args[]) file://聲明主方法 { thread threadone=new thread (); file://用Thread類的子類創建線程 Thread threado=new Thread(new thread ()); file://用Runnable介面類的對象創建線程 threadone start(); threado start(); file://strat()方法啟動線程 } }
運行該程序就可以看出 線程threadone和threado交替佔用CPU 處於並行運行狀態 可以看出 啟動線程的run()方法是通過調用線程的start()方法來實現的(見上例中主類) 調用start()方法啟動線程的run()方法不同於一般的調用方法 調用一般方法時 必須等到一般方法執行完畢才能夠返回start()方法 而啟動線程的run()方法後 start()告訴系統該線程准備就緒可以啟動run()方法後 就返回start()方法執行調用start()方法語句下面的語句 這時run()方法可能還在運行 這樣 線程的啟動和運行並行進行 實現了多任務操作
線程的優先順序
對於多線程程序 每個線程的重要程度是不盡相同 如多個線程在等待獲得CPU時間時 往往我們需要優先順序高的線程優先搶佔到CPU時間得以執行 又如多個線程交替執行時 優先順序決定了級別高的線程得到CPU的次數多一些且時間多長一些 這樣 高優先順序的線程處理的任務效率就高一些
Java中線程的優先順序從低到高以整數 ~ 表示 共分為 級 設置優先順序是通過調用線程對象的setPriority()方法 如上例中 設置優先順序的語句為
thread threadone=new thread (); file://用Thread類的子類創建線程
Thread threado=new Thread(new thread ()); file://用Runnable介面類的對象創建線程
threadone setPriority( ); file://設置threadone的優先順序
threado setPriority( ); file://設置threado的優先順序
threadone start(); threado start(); file://strat()方法啟動線程
這樣 線程threadone將會優先於線程threado執行 並將佔有更多的CPU時間 該例中 優先順序設置放在線程啟動前 也可以在啟動後進行設置 以滿足不同的優先順序需求
線程的(同步)控制
一個Java程序的多線程之間可以共享數據 當線程以非同步方式訪問共享數據時 有時候是不安全的或者不和邏輯的 比如 同一時刻一個線程在讀取數據 另外一個線程在處理數據 當處理數據的線程沒有等到讀取數據的線程讀取完畢就去處理數據 必然得到錯誤的處理結果 這和我們前面提到的讀取數據和處理數據並行多任務並不矛盾 這兒指的是處理數據的線程不能處理當前還沒有讀取結束的數據 但是可以處理其它的數據
如果我們採用多線程同步控制機制 等到第一個線程讀取完數據 第二個線程才能處理該數據 就會避免錯誤 可見 線程同步是多線程編程的一個相當重要的技術
在講線程的同步控制前我們需要交代如下概念
用Java關鍵字synchonized同步對共享數據操作的方法
在一個對象中 用synchonized聲明的方法為同步方法 Java中有一個同步模型 監視器 負責管理線程對對象中的同步方法的訪問 它的原理是 賦予該對象唯一一把 鑰匙 當多個線程進入對象 只有取得該對象鑰匙的線程才可以訪問同步方法 其它線程在該對象中等待 直到該線程用wait()方法放棄這把鑰匙 其它等待的線程搶占該鑰匙 搶佔到鑰匙的線程後才可得以執行 而沒有取得鑰匙的線程仍被阻塞在該對象中等待
file://聲明同步的一種方式 將方法聲明同步
class store {public synchonized void store_in(){… }public synchonized void store_out(){ … }}
利用wait() notify()及notifyAll()方法發送消息實現線程間的相互聯系
Java程序中多個線程通過消息來實現互動聯系的 這幾種方法實現了線程間的消息發送 例如定義一個對象的synchonized 方法 同一時刻只能夠有一個線程訪問該對象中的同步方法 其它線程被阻塞 通常可以用notify()或notifyAll()方法喚醒其它一個或所有線程 而使用wait()方法來使該線程處於阻塞狀態 等待其它的線程用notify()喚醒
一個實際的例子就是生產和銷售 生產單元將產品生產出來放在倉庫中 銷售單元則從倉庫中提走產品 在這個過程中 銷售單元必須在倉庫中有產品時才能提貨 如果倉庫中沒有產品 則銷售單元必須等待
程序中 假如我們定義一個倉庫類store 該類的實例對象就相當於倉庫 在store類中定義兩個成員方法 store_in() 用來模擬產品製造者往倉庫中添加產品 strore_out()方法則用來模擬銷售者從倉庫中取走產品 然後定義兩個線程類 customer類 其中的run()方法通過調用倉庫類中的store_out()從倉庫中取走產品 模擬銷售者 另外一個線程類procer中的run()方法通過調用倉庫類中的store_in()方法向倉庫添加產品 模擬產品製造者 在主類中創建並啟動線程 實現向倉庫中添加產品或取走產品
如果倉庫類中的store_in() 和store_out()方法不聲明同步 這就是個一般的多線程 我們知道 一個程序中的多線程是交替執行的 運行也是無序的 這樣 就可能存在這樣的問題
倉庫中沒有產品了 銷售者還在不斷光顧 而且還不停的在 取 產品 這在現實中是不可思義的 在程序中就表現為負值 如果將倉庫類中的stroe_in()和store_out()方法聲明同步 如上例所示 就控制了同一時刻只能有一個線程訪問倉庫對象中的同步方法 即一個生產類線程訪問被聲明為同步的store_in()方法時 其它線程將不能夠訪問對象中的store_out()同步方法 當然也不能訪問store_in()方法 必須等到該線程調用wait()方法放棄鑰匙 其它線程才有機會訪問同步方法
lishixin/Article/program/Java/gj/201311/27301
❷ 每個開發人員都應該知道的16個頂級新計算機編程語言
函數式語言
Elixir
Elixir 比 Erlang 更容易編寫,具有 Haskell 等語言的函數式編程概念。Elixir是基於Erlang 虛擬機的,其廣為人知的特點是運行低延時、分布式、可容錯的系統,並成功用於Web開發與嵌入式軟體領域。
Elm
Elm是一種用於構建 Web 應用程序的函數式語言。業內一般認為,它適用於創建高可交互應用,例如復雜的用戶界面,開發人員可以通過 Elm 快速編寫富有表現力的系統。Elm 也以沒有運行時異常而聞名。
PureScript
PureScript是一種可編譯為 JavaScript 的純函數式編程語言。與 Haskell 最相似的是,PureScript 最適合用於開發 Web 應用程序和伺服器端應用程序。
PureScript 支持類型推斷,與其他語言相比,需要明顯類型注釋要少得多。
Swift
Swift是一種由蘋果公司開發的通用編譯編程語言,最早的設想是替代上一代編程語言Objective-C ,過程中結合了Objective-C、Rust、Ruby 和 Python等語言的編程思想。目前Swift用於開發蘋果自己的手機、伺服器、台式機上的應用軟體。
程序語言
Go
Go語言是由谷歌公司創造的類似C風格的語言。Go 比 C++ 或 Java 更簡潔,比 Ruby 或 Python 更安全。
一些缺點: 編碼要求嚴格。比如,不能混用符號和無符號整數。還有一個明顯的遺漏,Go語言沒有泛型和繼承。
但Go語言的優勢同樣明顯,簡單且易於使用。Go語言擅長於網路和多線程方面的編程。
面向對象語言
DART
Dart同樣來自谷歌公司具有c語言風格。Dart可以輕松編寫JavaScript、Java for Android、本地機器代碼或獨立的 Dart 虛擬機。它還可以運行後端代碼。
Dart 非常適合使用事件驅動代碼構建用戶界面。根據Dart 團隊成員的說法,Dart的優勢:可選的靜態類型、最小的編譯時錯誤和強大的內置編輯器。
Pony
Pony是一種基於無數據競爭類型和垃圾收集的語言,並使用 actor 模型以及稱為引用功能的東西。
你可以把 Pony 想像成某種「Rust 遇上 Erlang」的復合體,沒有鎖,高並發是其主要優點。
Pony 的缺點是 API 穩定性低、很少有高質量的第三方庫和有限的本地工具。
TypeScript
TypeScript是一個基於 JavaScript 靜態類型定義構建,並由微軟維護且開源編程語言。Visual Studio Code 或Visual Studio 是推薦的IDE編輯器,微軟大廠的用戶體驗和錯誤檢查也不用懷疑。
復合編程語言
Hack
Hack是一種作為 PHP 方言的 HipHop 虛擬機的編程語言。於 2014 年由Facebook創建,允許程序員同時使用靜態和動態類型(也稱為漸進類型),這為編碼提供了靈活性。
Julia
Julia是一種高級通用編程語言,用於計算科學和數值分析。Julia 以動態類型和可重現的高性能特性而聞名。
Julia 在數據可視化和機器學習等方面都有大量用途。事實上,它被英國保險公司 Aviva 用於風險計算,紐約聯邦儲備銀行用於金融建模,甚至氣候建模聯盟用於氣候變化建模。它擁有Fortran、C++、R、Java、C 、Python等的介面,這使其成為最受追捧的新語言之一。
Kotlin
Kotlin是運行在 Java 虛擬機中的更快、更流暢的 Java 版本。它現在是Android 開發的首選語言。根據 Android 開發者網站顯示,程序員正轉而採用 Kotlin,因為該語言的樣板代碼更少,空指針異常更少,並且與 Java 有互操作性。
Kotlin 可用於在 iOS 和 Android 上運行的應用程序、不使用額外運行時或虛擬機。
Nim
Nim是一種優先考慮可讀性的靜態類型語言。通過結合多種語言的特性,Nim 為程序員提供了速度和易用性。
它帶有 JavaScript 後端、分散的包管理、自動內存管理、C 和 C++ 庫的綁定以及用於調試的回溯。作為一種語言,Nim 是有限的,但它包含一組元編程功能,如泛型、模板和宏,因此開發人員可以在避免冗長代碼的同時以不同的風格工作。
OCaml作為此列表中較舊的語言,OCaml是一種多範式語言——既有函數式、命令式和類型安全,也具有面向對象功能。
OCaml 的一些優勢:定義數據類型很容易。默認情況下,所有變數都是不可變的。API 穩定,具有良好的庫向後兼容性。該語言還為獨立應用程序提供自動內存管理和單獨編譯。
Reason
如果比JavaScript 更快、更簡單且類型安全會怎樣?
這就是創建Reason的 Facebook 開發者想要回答的問題。不過,他並沒有從頭開始構建一種新語言,而是採用了 OCaml,並將其調整為類似於 JavaScript。
Reason使用項目 BucketScript編譯為 JavaScript,並且可以訪問 80% 的 JavaScript 工具和生態系統。它還可以編譯為准系統、iOS、Android 和微控制器。
Red
Red是一種最初旨在克服 Rebol 語言限制的編程語言。Red 於 2011 年推出,受 Rebol、Lua 和 Scala 等語言的影響,對高級和低級編程都很有用。
該語言可用於開發從高級 GUI 到低級操作系統的所有方面。Red 擁有人性化的語法、低內存佔用和垃圾收集等優點。
Rust
Rust解決了一些與 Go 相同的問題,如系統級別的線程和進程安全,,但Rust 更像 C 風格的語法
但Rust語言的缺點:靜態類型和缺乏垃圾收集
Rust可直接訪問內存意味著程序員可以編寫低級代碼,如操作系統內核。Rust 也非常適合嵌入式設備、網路服務和命令行編寫。
❸ c語言如何編寫一個簡單的多線程程序
這是一個多線程例子,裡面只有兩個線程,是生產者/消費者模式,已編譯通過,注釋很詳細,x0dx0a如下:x0dx0ax0dx0a/* 以生產者和消費者模型問題來闡述Linux線程的控制和通信你 x0dx0a 生產者線程將生產的產品送入緩沖區,消費者線程則從中取出產品。x0dx0a 緩沖區有N個,是一個環形的緩沖池。x0dx0a */x0dx0a#include
❹ C語言多線程的優勢
線程程序作為一種多任務、並發的工作方式,當然有其存在優勢:
提高應用程序響應:
這對圖形界面的程序尤其有意義,當一個操作耗時很長時,整個系統都會等待這個操作,此時程序不會響應鍵盤、滑鼠、菜單的操作,而使用多線程技術,將耗時長的操作(time consuming)置於一個新的線程,可以避免這種尷尬的情況。
使多CPU系統更加有效:
操作系統會保證當線程數不大於CPU數目時,不同的線程運行於不同的CPU上。
改善程序結構:
一個既長又復雜的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分,這樣的程序會利於理解和修改。
❺ 關於C++多線程編程教學
在Windows NT和Windows 9x中,多線程的編程實現需要調用一系列的API函數,如CreateThread、ResumeThread等,比較麻煩而且容易出錯。我們使用Inprise公司的新一代RAD開發工具C++Builder,可以方便地實現多線程的編程。與老牌RAD工具Visual Basic和Delphi比,C++Builer不僅功能非常強大,而且它的編程語言是C++,對於系統開發語言是C的Windows系列操作系統,它具有其它編程語言無可比擬的優勢。利用C++Builder提供的TThread對象,多線程的編程變得非常簡便易用。那麼,如何實現呢?且待我慢慢道來,讓你體會一下多線程的強大功能。
1. 創建多線程程序:
首先,先介紹一下實現多線程的具體步驟。在C++Builder中雖然用Tthread對象說明了線程的概念,但是Tthread對象本身並不完整,需要在TThread下新建其子類,並重載Execute方法來使用線程對象。在C++Builder下可以很方便地實現這一點。
在C++Builder IDE環境下選擇菜單File|New,在New欄中選中Thread Object,按OK,接下來彈出輸入框,輸入TThread對象子類的名字MyThread,這樣C++Builder自動為你創建了一個名為TMyThread的TThread子類。同時編輯器中多了一個名為Unit2.cpp的單元,這就是我們創建的TMyThread子類的原碼,如下:
#include
#pragma hdrstop
#include 「Unit2.h」
#pragma package(smart_init)
//---------------------
// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall MyThread::UpdateCaption()
// {
// Form1->Caption = 「Updated in a thread」;
// }
//--------------------
__fastcall MyThread::MyThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//--------------------
void __fastcall MyThread::Execute()
{
//---- Place thread code here ----
}
//---------------------
其中的Execute()函數就是我們要在線程中實現的任務的代碼所在處。在原代碼中包含Unit2.cpp,這個由我們創建的TMyThread對象就可以使用了。使用時,動態創建一個TMyThread 對象,在構造函數中使用Resume()方法,那麼程序中就增加了一個新的我們自己定義的線程TMyThread,具體執行的代碼就是Execute()方法重載的代碼。要載入更多的線程,沒關系,只要繼續創建需要數量的TMyThread 對象就成。
❻ 什麼是Java多線程
多線程的概念?
說起多線程,那麼就不得不說什麼是線程,而說起線程,又不得不說什麼是進程。
進程(Process)是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。在早期面向進程設計的計算機結構中,進程是程序的基本執行實體;在當代面向線程設計的計算機結構中,進程是線程的容器。程序是指令、數據及其組織形式的描述,進程是程序的實體。
進程可以簡單的理解為一個可以獨立運行的程序單位。它是線程的集合,進程就是有一個或多個線程構成的,每一個線程都是進程中的一條執行路徑。
那麼多線程就很容易理解:多線程就是指一個進程中同時有多個執行路徑(線程)正在執行。
為什麼要使用多線程?
1.在一個程序中,有很多的操作是非常耗時的,如資料庫讀寫操作,IO操作等,如果使用單線程,那麼程序就必須等待這些操作執行完成之後才能執行其他操作。使用多線程,可以在將耗時任務放在後台繼續執行的同時,同時執行其他操作。
2.可以提高程序的效率。
3.在一些等待的任務上,如用戶輸入,文件讀取等,多線程就非常有用了。
缺點:
1.使用太多線程,是很耗系統資源,因為線程需要開辟內存。更多線程需要更多內存。
2.影響系統性能,因為操作系統需要在線程之間來回切換。
3.需要考慮線程操作對程序的影響,如線程掛起,中止等操作對程序的影響。
4.線程使用不當會發生很多問題。
總結:多線程是非同步的,但這不代表多線程真的是幾個線程是在同時進行,實際上是系統不斷地在各個線程之間來回的切換(因為系統切換的速度非常的快,所以給我們在同時運行的錯覺)。
2.多線程與高並發的聯系。
高並發:高並發指的是一種系統運行過程中遇到的一種「短時間內遇到大量操作請求」的情況,主要發生在web系統集中大量訪問或者socket埠集中性收到大量請求(例如:12306的搶票情況;天貓雙十一活動)。該情況的發生會導致系統在這段時間內執行大量操作,例如對資源的請求,資料庫的操作等。如果高並發處理不好,不僅僅降低了用戶的體驗度(請求響應時間過長),同時可能導致系統宕機,嚴重的甚至導致OOM異常,系統停止工作等。如果要想系統能夠適應高並發狀態,則需要從各個方面進行系統優化,包括,硬體、網路、系統架構、開發語言的選取、數據結構的運用、演算法優化、資料庫優化……。
而多線程只是在同/非同步角度上解決高並發問題的其中的一個方法手段,是在同一時刻利用計算機閑置資源的一種方式。
多線程在高並發問題中的作用就是充分利用計算機資源,使計算機的資源在每一時刻都能達到最大的利用率,不至於浪費計算機資源使其閑置。
3.線程的創建,停止,常用方法介紹。
1.線程的創建:
線程創建主要有2種方式,一種是繼承Thread類,重寫run方法即可;(Thread類實現了Runable介面)
另一種則是實現Runable介面,也需要重寫run方法。
線程的啟動,調用start()方法即可。 我們也可以直接使用線程對象的run方法,不過直接使用,run方法就只是一個普通的方法了。
其他的還有: 通過匿名內部類的方法創建;實現Callable介面。。。。。
2.線程常用方法:
currentThread()方法:該方法返回當前線程的信息 .getName()可以返回線程名稱。
isAlive()方法:該方法判斷當前線程是否處於活動狀態。
sleep()方法:該方法是讓「當前正在執行的線程「休眠指定的時間,正在執行的線程是指this.currentThread()返回的線程。
getId()方法:該方法是獲取線程的唯一標識。
3.線程的停止:
在java中,停止線程並不簡單,不想for。。break那樣說停就停,需要一定的技巧。
線程的停止有3種方法:
1.線程正常終止,即run()方法運行結束正常停止。
2.使用interrupt方法中斷線程。
3.使用stop方法暴力停止線程。
interrupt方法中斷線程介紹:
interrupt方法其實並不是直接中斷線程,只是給線程添加一個中斷標志。
判斷線程是否是停止狀態:
this.interrupted(); 判斷當前線程是否已經中斷。(判斷的是這個方法所在的代碼對應的線程,而不是調用對象對應的線程)
this.isInterrupted(); 判斷線程是否已經中斷。(誰調用,判斷誰)
註:.interrupted()與isInterrupted()的區別:
interrupted()方法判斷的是所在代碼對應的線程是否中斷,而後者判斷的是調用對象對應的線程是否停止
前者執行後有清除狀態的功能(如連續調用兩次時,第一次返回true,則第二次會返回false)
後者沒有清除狀態的功能(兩次返回都為true)
真正停止線程的方法:
異常法:
在run方法中 使用 this.interrupted();判斷線程終止狀態,如果為true則 throw new interruptedException()然後捕獲該異常即可停止線程。
return停止線程:
在run方法中 使用 this.interrupted();判斷線程終止狀態,如果為true則return停止線程。 (建議使用異常法停止線程,因為還可以在catch中使線程向上拋,讓線程停止的事件得以傳播)。
暴力法:
使用stop()方法強行停止線程(強烈不建議使用,會造成很多不可預估的後果,已經被標記為過時)
(使用stop方法會拋出 java.lang.ThreadDeath 異常,並且stop方法會釋放鎖,很容易造成數據不一致)
註:在休眠中停止線程:
在sleep狀態下停止線程 會報異常,並且會清除線程狀態值為false;
先停止後sleep,同樣會報異常 sleep interrupted;
4.守護線程。
希望對您有所幫助!~
❼ Java多線程編程
作者 natrium 一 理解多線程多線程是這樣一種機制 它允許在程序中並發執行多個指令流 每個指令流都稱為一個線程 彼此間互相獨立 線程又稱為輕量級進程 它和進程一樣擁有獨立的執行控制 由操作系統負責調度 區別在於線程沒有獨立的存儲空間 而是和所屬進程中的其它線程共享一個存儲空間 這使得線程間的通信遠較進程簡單 多個線程的執行是並發的 也就是在邏輯上 同時 而不管是否是物理上的 同時 如果系統只有一個CPU 那麼真正的 同時 是不可能的 但是由於CPU的速度非常快 用戶感覺不到其中的區別 因此我們也不用關心它 只需要設想各個線程是同時執行即可 多線程和傳統的單線程在程序設計上最大的區別在於 由於各個線程的控制流彼此獨立 使得各個線程之間的代碼是亂序執行的 由此帶來的線程調度 同步等問題 將在以後探討 二 在Java中實現多線程我們不妨設想 為了創建一個新的線程 我們需要做些什麼?很顯然 我們必須指明這個線程所要執行的代碼 而這就是在Java中實現多線程我們所需要做的一切!真是神奇!Java是如何做到這一點的?通過類!作為一個完全面向對象的語言 Java提供了類 java lang Thread 來方便多線程編程 這個類提供了大量的方法來方便我們控制自己的各個線程 我們以後的討論都將圍繞這個類進行 那麼如何提供給 Java 我們要線程執行的代碼呢?讓我們來看一看 Thread 類 Thread 類最重要的方法是 run() 它為Thread 類的方法 start() 所調用 提供我們的線程所要執行的代碼 為了指定我們自己的代碼 只需要覆蓋它!方法一 繼承 Thread 類 覆蓋方法 run() 我們在創建的 Thread 類的子類中重寫 run() 加入線程所要執行的代碼即可 下面是一個例子 public class MyThread extends Thread {int count= number;public MyThread(int num) {number = num;System out println( 創建線程 + number);}public void run() {while(true) {System out println( 線程 + number + :計數 + count);if(++count== ) return;}}public static void main(String args[]) {for(int i = ; i < 5; i++) new MyThread(i+1).start();}}這種方法簡單明了,符合大家的習慣,但是,它也有一個很大的缺點,那就是如果我們的類已經從一個類繼承(如小程序必須繼承自 Applet 類),則無法再繼承 Thread 類,這時如果我們又不想建立一個新的類,應該怎麼辦呢?我們不妨來探索一種新的方法:我們不創建 Thread 類的子類,而是直接使用它,那麼我們只能將我們的方法作為參數傳遞給 Thread 類的實例,有點類似回調函數。.WINgWIT.但是 Java 沒有指針,我們只能傳遞一個包含這個方法的類的實例。那麼如何限制這個類必須包含這一方法呢?當然是使用介面!(雖然抽象類也可滿足,但是需要繼承,而我們之所以要採用這種新方法,不就是為了避免繼承帶來的限制嗎?)Java 提供了介面 java.lang.Runnable 來支持這種方法。方法二:實現 Runnable 介面Runnable 介面只有一個方法 run(),我們聲明自己的類實現 Runnable 介面並提供這一方法,將我們的線程代碼寫入其中,就完成了這一部分的任務。但是 Runnable 介面並沒有任何對線程的支持,我們還必須創建 Thread 類的實例,這一點通過 Thread 類的構造函數public Thread(Runnable target);來實現。下面是一個例子:public class MyThread implements Runnable {int count= 1, number;public MyThread(int num) {number = num;System.out.println("創建線程 " + number);}public void run() {while(true) {System.out.println("線程 " + number + ":計數 " + count);if(++count== 6) return;} }public static void main(String args[]) {for(int i = 0; i < 5; i++) new Thread(new MyThread(i+1)).start();}}嚴格地說,創建 Thread 子類的實例也是可行的,但是必須注意的是,該子類必須沒有覆蓋 Thread 類的 run 方法,否則該線程執行的將是子類的 run 方法,而不是我們用以實現Runnable 介面的類的 run 方法,對此大家不妨試驗一下。使用 Runnable 介面來實現多線程使得我們能夠在一個類中包容所有的代碼,有利於封裝,它的缺點在於,我們只能使用一套代碼,若想創建多個線程並使各個線程執行不同的代碼,則仍必須額外創建類,如果這樣的話,在大多數情況下也許還不如直接用多個類分別繼承 Thread 來得緊湊。綜上所述,兩種方法各有千秋,大家可以靈活運用。下面讓我們一起來研究一下多線程使用中的一些問題。三:線程的四種狀態1. 新狀態:線程已被創建但尚未執行(start() 尚未被調用)。2. 可執行狀態:線程可以執行,雖然不一定正在執行。CPU 時間隨時可能被分配給該線程,從而使得它執行。3. 死亡狀態:正常情況下 run() 返回使得線程死亡。調用 stop()或 destroy() 亦有同樣效果,但是不被推薦,前者會產生異常,後者是強制終止,不會釋放鎖。4. 阻塞狀態:線程不會被分配 CPU 時間,無法執行。四:線程的優先順序 線程的優先順序代表該線程的重要程度,當有多個線程同時處於可執行狀態並等待獲得 CPU 時間時,線程調度系統根據各個線程的優先順序來決定給誰分配 CPU 時間,優先順序高的線程有更大的機會獲得 CPU 時間,優先順序低的線程也不是沒有機會,只是機會要小一些罷了。你可以調用 Thread 類的方法 getPriority() 和 setPriority()來存取線程的優先順序,線程的優先順序界於1(MIN_PRIORITY)和10(MAX_PRIORITY)之間,預設是5(NORM_PRIORITY)。五:線程的同步由於同一進程的多個線程共享同一片存儲空間,在帶來方便的同時,也帶來了訪問沖突這個嚴重的問題。Java語言提供了專門機制以解決這種沖突,有效避免了同一個數據對象被多個線程同時訪問。由於我們可以通過 private 關鍵字來保證數據對象只能被方法訪問,所以我們只需針對方法提出一套機制,這套機制就是 synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。1. synchronized 方法:通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。如:public synchronized void accessVal(int newVal);synchronized 方法控制對類成員變數的訪問:每個類實例對應一把鎖,每個 synchronized 方法都必須獲得調用該方法的類實例的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此後被阻塞的線程方能獲得該鎖,重新進入可執行狀態。這種機制確保了同一時刻對於每一個類實例,其所有聲明為 synchronized 的成員函數中至多隻有一個處於可執行狀態(因為至多隻有一個能夠獲得該類實例對應的鎖),從而有效避免了類成員變數的訪問沖突(只要所有可能訪問類成員變數的方法均被聲明為 synchronized)。在 Java 中,不光是類實例,每一個類也對應一把鎖,這樣我們也可將類的靜態成員函數聲明為 synchronized ,以控制其對類的靜態成員變數的訪問。synchronized 方法的缺陷:若將一個大的方法聲明為synchronized 將會大大影響效率,典型地,若將線程類的方法 run() 聲明為 synchronized ,由於在線程的整個生命期內它一直在運行,因此將導致它對本類任何 synchronized 方法的調用都永遠不會成功。當然我們可以通過將訪問類成員變數的代碼放到專門的方法中,將其聲明為 synchronized ,並在主方法中調用來解決這一問題,但是 Java 為我們提供了更好的解決辦法,那就是 synchronized 塊。2. synchronized 塊:通過 synchronized關鍵字來聲明synchronized 塊。語法如下: synchronized(syncObject) {//允許訪問控制的代碼}synchronized 塊是這樣一個代碼塊,其中的代碼必須獲得對象 syncObject (如前所述,可以是類實例或類)的鎖方能執行,具體機制同前所述。由於可以針對任意代碼塊,且可任意指定上鎖的對象,故靈活性較高。六:線程的阻塞為了解決對共享存儲區的訪問沖突,Java 引入了同步機制,現在讓我們來考察多個線程對共享資源的訪問,顯然同步機制已經不夠了,因為在任意時刻所要求的資源不一定已經准備好了被訪問,反過來,同一時刻准備好了的資源也可能不止一個。為了解決這種情況下的訪問控制問題,Java 引入了對阻塞機制的支持。阻塞指的是暫停一個線程的執行以等待某個條件發生(如某資源就緒),學過操作系統的同學對它一定已經很熟悉了。Java 提供了大量方法來支持阻塞,下面讓我們逐一分析。1. sleep() 方法:sleep() 允許 指定以毫秒為單位的一段時間作為參數,它使得線程在指定的時間內進入阻塞狀態,不能得到CPU 時間,指定的時間一過,線程重新進入可執行狀態。典型地,sleep() 被用在等待某個資源就緒的情形:測試發現條件不滿足後,讓線程阻塞一段時間後重新測試,直到條件滿足為止。2. suspend() 和 resume() 方法:兩個方法配套使用,suspend()使得線程進入阻塞狀態,並且不會自動恢復,必須其對應的resume() 被調用,才能使得線程重新進入可執行狀態。典型地,suspend() 和 resume() 被用在等待另一個線程產生的結果的情形:測試發現結果還沒有產生後,讓線程阻塞,另一個線程產生了結果後 lishixin/Article/program/Java/gj/201311/27622
❽ 什麼是Java多線程編程
一、 什麼是多線程:
我們現在所使用操作系統都是多任務操作系統(早期使用的DOS操作系統為單任務操作系統),多任務操作指在同一時刻可以同時做多件事(可以同時執行多個程序)。
多進程:每個程序都是一個進程,在操作系統中可以同時執行多個程序,多進程的目的是為了有效的使用CPU資源,每開一個進程系統要為該進程分配相關的系統資源(內存資源)
多線程:線程是進程內部比進程更小的執行單元(執行流|程序片段),每個線程完成一個任務,每個進程內部包含了多個線程每個線程做自己的事情,在進程中的所有線程共享該進程的資源;
主線程:在進程中至少存在一個主線程,其他子線程都由主線程開啟,主線程不一定在其他線程結束後結束,有可能在其他線程結束前結束。Java中的主線程是main線程,是Java的main函數;
繼承Thread類來實現多線程:
二、 Java中實現多線程的方式:
當我們自定義的類繼承Thread類後,該類就為一個線程類,該類為一個獨立的執行單元,線程代碼必須編寫在run()方法中,run方法是由Thread類定義,我們自己寫的線程類必須重寫run方法。
run方法中定義的代碼為線程代碼,但run方法不能直接調用,如果直接調用並沒有開啟新的線程而是將run方法交給調用的線程執行
要開啟新的線程需要調用Thread類的start()方法,該方法自動開啟一個新的線程並自動執行run方法中的內容
java多線程的啟動順序不一定是線程執行的順序,各個線程之間是搶佔CPU資源執行的,所有有可能出現與啟動順序不一致的情況。
CPU的調用策略:
如何使用CPU資源是由操作系統來決定的,但操作系統只能決定CPU的使用策略不能控制實際獲得CPU執行權的程序。
線程執行有兩種方式:
1.搶占式:
目前PC機中使用最多的一種方式,線程搶佔CPU的執行權,當一個線程搶到CPU的資源後並不是一直執行到此線程執行結束,而是執行一個時間片後讓出CPU資源,此時同其他線程再次搶佔CPU資源獲得執行權。
2.輪循式;
每個線程執行固定的時間片後讓出CPU資源,以此循環執行每個線程執行相同的時間片後讓出CPU資源交給下一個線程執行。
希望對您有所幫助!~