java多線程是指: 多線程一種機制,它允許在程式中並發執行多個指令流,每個指令流稱為一個線程,彼此間互相獨立,Java中所有變數都儲存在主記憶體中,對於所有執行緒都是共享的。
java多執行緒詳解:
一、理解多執行緒
# 多線程是這樣一種機制,它允許在程式中並發執行多個指令流,每個指令流都稱為一個線程,彼此間互相獨立。執行緒又稱為輕量級進程,它和進程一樣擁有獨立的執行控制,由作業系統負責調度,區別在於執行緒沒有獨立的儲存空間,而是和所屬進程中的其它執行緒共享一個儲存空間,這使得執行緒間的通訊遠較進程簡單。
具體到java記憶體模型,由於Java設計為跨平台的語言,在記憶體管理上,顯然也要有一個統一的模型。系統存在一個主記憶體(Main Memory), Java中所有變數都儲存在主記憶體中,對於所有執行緒都是共享的。每個執行緒都有自己的工作記憶體(Working Memory),工作記憶體中保存的是主記憶體中某些變數的拷貝,執行緒對所有變數的操作都是在工作記憶體中進行,執行緒之間無法相互直接存取,變數傳遞均需透過主存完成。
多個執行緒的執行是並發的,也就是在邏輯上“同時”,而不管是否是物理上的“同時”。如果系統只有一個CPU,那麼真正的「同時」是不可能的。多執行緒和傳統的單執行緒在程式設計上最大的差別在於,由於各個執行緒的控制流程彼此獨立,使得各個執行緒之間的程式碼是亂序執行的,將會帶來執行緒調度,同步等問題。網管網bitsCN.com
相關學習推薦:java基礎教學
二、在Java中實作多執行緒
我們不妨設想,為了創建一個新的線程,我們需要做些什麼?很顯然,我們必須指明這個執行緒所要執行的程式碼,而這就是在Java中實作多執行緒我們所需要做的一切!
作為一個完全物件導向的語言,Java提供了類別 java.lang.Thread 來方便多執行緒編程,這個類別提供了大量的方法來方便我們控制自己的各個執行緒。
那麼如何提供給 Java 我們要執行緒執行的程式碼呢?讓我們來看看 Thread 類別。 Thread 類別最重要的方法是 run() ,它為Thread 類別的方法 start() 所調用,提供我們的執行緒所要執行的程式碼。為了指定我們自己的程式碼,只需要覆蓋它!
方法一:繼承 Thread 類,重寫方法 run(),我們在創建的 Thread 類別的子類別中重寫 run() ,加入執行緒所要執行的程式碼即可。以下是一個例子:
public class TwoThread extends Thread { public void run() { for ( int i = 0; i < 10; i++ ) { System.out.println("New thread"); } } public static void main(String[] args) { TwoThread tt = new TwoThread(); tt.start(); for ( int i = 0; i < 10; i++ ) { System.out.println("Main thread"); } } }
這個方法簡單明了,符合大家的習慣,但是,它也有一個很大的缺點,那就是如果我們的類別已經從一個類別繼承,則無法再繼承Thread類。
方法二:實作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(); } }
使用 Runnable 介面來實作多執行緒使得我們能夠在一個類別中包容所有的程式碼,有利於封裝下面讓我們一起來研究一下多執行緒使用中的一些問題。
三、執行緒的四種狀態
1、新狀態:執行緒已建立但尚未執行(start() 尚未被呼叫)。
2、可執行狀態:執行緒可以執行,雖然不一定正在執行。 CPU 時間隨時可能被指派給該執行緒,從而使得它執行。
3、阻塞狀態:執行緒不會被分配 CPU 時間,無法執行;可能阻塞於I/O,或阻塞於同步鎖定。
4、死亡狀態:正常情況下run() 回傳使得執行緒死亡。呼叫 stop()或 destroy() 亦有相同效果,但是不被推薦,前者會產生異常,後者是強制終止,不會釋放鎖。
四、執行緒的優先權
线程的优先级代表该线程的重要程度,当有多个线程同时处于可执行状态并等待获得 CPU 时间时,线程调度系统根据各个线程的优先级来决定给谁分配 CPU 时间,优先级高的线程有更大的机会获得 CPU 时间,优先级低的线程也不是没有机会,只是机会要小一些罢了。
你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取线程的优先级,线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间,缺省是5(NORM_PRIORITY)。
五、线程的同步
由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。
我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法:通过在方法声明中加入synchronized关键字来声明 synchronized 方法。synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized,以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法run()声明为synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何synchronized方法的调用都永远不会成功。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) { //允许访问控制的代码 }
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject 的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
相关学习推荐:编程视频
以上是java多執行緒指的是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!