Java-并发入门
文章目錄
- 概述
- 線程的生命周期
- 線程優先級
- 創建線程的兩種方式
- 通過實現Runnable接口創建一個線程
- 通過擴展Thread類創建一個線程
- 線程的主要操作
- Thread.stop()廢棄原因
- Thread.suspend()、resume()廢棄原因
- 線程間通信
- 主要方法
概述
多線程程序包含兩個或多個可同時運行的部分,每個部分可以同時處理不同的任務,從而能更好地利用可用資源,特別是當計算機有多個CPU的時候。
多線程夠寫入多個活動,可以在同一程序中同時進行操作處理。
根據定義,多任務是當多個進程共享,如CPU處理公共資源。
多線程將多任務的概念擴展到可以將單個應用程序中的特定操作細分為單個線程的應用程序。每個線程可以并行運行。
操作系統不僅在不同的應用程序之間劃分處理時間,而且在應用程序中的每個線程之間劃分處理時間。
多線程能夠在同一程序同中,進行多個活動的方式進行寫入。
線程的生命周期
線程從創建到運行完成要經歷下面這些階段:
- New
- Runnable
- Running
- Non-Runnable (blocked) / Waiting
- Terminated
New: 該狀態指已經創建了該線程類的實例,但是還沒有調用 start() 方法。
Runnable: 該狀態指線程已經調用了 start() 方法,已經可以運行了,正在等待線程調度器來運行。
Running: 該狀態指此線程已經被線程調度器選中并正在運行中。
Non-Runnable (blocked): 該狀態指線程還存在但是沒有資格運行??赡艿脑蛴?#xff1a;sleep 操作、等待文件 I/O 的完成或等待釋放鎖狀態等等。
Terminated: 該狀態指線程已經運行結束,處于中止狀態, run() 方法已經退出。
線程優先級
每個Java線程都有一個優先級,可以幫助操作系統確定安排線程的順序。
Java線程優先級在MIN_PRIORITY(常數為1)和MAX_PRIORITY(常數為10)之間的范圍內。
默認情況下,每個線程都被賦予優先級NORM_PRIORITY(常數為5)。
具有較高優先級的線程對于一個程序來說更重要,應該在低優先級線程之前分配處理器時間。 然而,線程優先級不能保證線程執行的順序,并且依賴于平臺。
創建線程的兩種方式
通過實現Runnable接口創建一個線程
- 第一步:
實現由Runnable接口提供的run()方法。 該方法為線程提供了一個入口點,該方法中存放完整的業務邏輯。
public void run()- 第二步:
實例化一個Thread對象,通過Thread提供的以下構造函數
Thread(Runnable threadObj, String threadName);threadObj:實現Runnable接口的類的實例
threadName :新線程的名稱
- 第三步:
創建了一個線程對象,可以通過調用start()方法啟動它,該方法執行對run()方法的調用.
package com.xgj.master.java.concurrency;public class RunnableDemo implements Runnable {private String threadName;private Thread thread;/*** * @Title:CreateThreadByRunnable* @Description:構造函數* @param threadName*/public RunnableDemo(String threadName) {this.threadName = threadName;System.out.println("Create thread:" + threadName);}/*** * @Title: run* @Description: 重寫Runnable接口中的run方法,業務邏輯存在與該方法中* @return: void*/@Overridepublic void run() {System.out.println("Running " + threadName );try {for (int i = 0 ; i < 5 ; i++) {System.out.println("ThreadName:" + threadName + " : " + i);// 睡眠0.5秒Thread.sleep(500);}} catch (InterruptedException e) {e.printStackTrace();System.out.println("Thread " + threadName + " interrupted.");} System.out.println("Thread " + threadName + " exiting.");}/*** * @Title: startThread* @Description: 如果線程對象為空,創建并啟動線程 ,通過調用thread.start()方法啟動線程,該方法執行對run()方法的調用.* @return: void*/public void startThread(){if( thread == null){thread = new Thread(this, threadName);thread.start();}}} package com.xgj.master.java.concurrency;public class RunnableDemoTest {public static void main(String[] args) {RunnableDemo thread1 = new RunnableDemo("thread-1");thread1.startThread();RunnableDemo thread2 = new RunnableDemo("thread-2");thread2.startThread();}}
運行結果(每次運行的結果不盡相同)
Create thread:thread-1 Create thread:thread-2 Running thread-1 ThreadName:thread-1 : 0 Running thread-2 ThreadName:thread-2 : 0 ThreadName:thread-1 : 1 ThreadName:thread-2 : 1 ThreadName:thread-1 : 2 ThreadName:thread-2 : 2 ThreadName:thread-1 : 3 ThreadName:thread-2 : 3 ThreadName:thread-2 : 4 ThreadName:thread-1 : 4 Thread thread-1 exiting. Thread thread-2 exiting.通過擴展Thread類創建一個線程
我們通過繼承Thread類,來重寫上面的例子
package com.xgj.master.java.concurrency;public class ThreadDemo extends Thread {private Thread t;private String threadName;/*** * @Title:ThreadDemo* @Description:構造函數,實例化一個帶有ThreadName的線程* @param threadName*/public ThreadDemo(String threadName) {this.threadName = threadName;System.out.println("Creating " + threadName);}/*** * @Title: run* @Description: 業務邏輯存在與該方法中* @return: void*/public void run() {System.out.println("Running " + threadName);try {for (int i = 0; i < 5; i++) {System.out.println("Thread: " + threadName + ", " + i);// 睡眠0.5秒Thread.sleep(500);}} catch (InterruptedException e) {System.out.println("Thread " + threadName + " interrupted.");}System.out.println("Thread " + threadName + " exiting.");}/*** * @Title: startThread* @Description: 如果線程對象為空,創建并啟動線程 ,通過調用thread.start()方法啟動線程,該方法執行對run()方法的調用.* @return: void*/public void startThread() {System.out.println("Starting " + threadName);if (t == null) {t = new Thread(this, threadName);t.start();}} } package com.xgj.master.java.concurrency;public class ThreadDemoTest {public static void main(String[] args) {ThreadDemo threadDemo1 = new ThreadDemo("Thread-1");threadDemo1.start();ThreadDemo threadDemo2 = new ThreadDemo("Thread-2");threadDemo2.start();}}運行結果(每次運行的結果不盡相同)
Creating Thread-1 Creating Thread-2 Running Thread-1 Thread: Thread-1, 0 Running Thread-2 Thread: Thread-2, 0 Thread: Thread-2, 1 Thread: Thread-1, 1 Thread: Thread-1, 2 Thread: Thread-2, 2 Thread: Thread-2, 3 Thread: Thread-1, 3 Thread: Thread-2, 4 Thread: Thread-1, 4 Thread Thread-1 exiting. Thread Thread-2 exiting.線程的主要操作
-
已廢棄 public void suspend() 該方法使線程處于掛起狀態,可以使用resume()方法恢復。
-
已廢棄 public void stop() 該方法使線程完全停止。
-
已廢棄 public void resume() 該方法恢復使用suspend()方法掛起的線程。
-
public void wait() 導致當前線程等到另一個線程調用notify()。
-
public void notify() 喚醒在此對象監視器上等待的單個線程。
JDK1.2之后已經不再使用suspend(),resume()和stop()方法。
Thread.stop()廢棄原因
stop方法會解除被加鎖的對象的鎖,因而可能造成這些對象處于不一致的狀態,而且這個方法造成的ThreadDeath異常不像其他的檢查期異常一樣被捕獲。
可以使用interrupt方法代替。
事實上,如果一個方法不能被interrupt,那stop方法也不會起作用。
Thread.suspend()、resume()廢棄原因
suspend/resume方法容易發生死鎖。
使用suspend時,并不會釋放鎖;假設先獲取該鎖,再進行resume,就會造成死鎖。
可以使用Object的wait和notify方法代替。wait方法會釋放持有的鎖。
線程間通信
主要方法
- public void wait() 使當前線程等到另一個線程調用notify()方法。
- public void notify() 喚醒在此對象監視器上等待的單個線程。
- public void notifyAll() 喚醒所有在同一個對象上調用wait()的線程。
上述幾個方法方法已被實現為Object中的final方法,因此它們在所有類中都可用。 所有這三種方法只能從同步上下文中調用。
總結
- 上一篇: 记一次Weblogic连接池泄露的修复过
- 下一篇: AS插件-Android Layout