一,線程的概念:進程中的獨立控制單元,線程控制着進程的執行;一個進程至少有一個線程。注:Java虛擬機啓動時不止一個線程,還有垃圾回收線程
二,線程的創建:
1. 繼承Thread類,重寫Run()方法
線程的啓動:
class MyThread extends Thread {
publicvoid run() {
// 線程執行的操作
}
}
new MyThread().start();
2. 實現Runnable接口,重寫Run()方法(推薦使用,避免了Java的單繼承侷限性)
線程的啓動:
Class MyThread implements Runnable{
publicvoid run() {
// 線程執行的操作
}
}
new Thread(new MyThread()).start();
三,多線程的安全問題:
原因:當多條語句同時被多個線程執行,某一個線程在執行了部分代碼卻沒有執行完的時候另一個線程也參與進來執行,導致共享數據錯誤
解決方式:1.同步代碼塊
Synchronized(對象){
//需要被同步的代碼
}
2同步函數(同步函數的鎖是this,靜態同步函數的鎖是Class對象)
Public Synchronizedvoid test(){
}
注:同步的前提:1.必須要有兩個或兩個以上線程在運行;2.多線程必須使用同一個鎖
同步的優缺點:優點:保證的共享數據的安全;缺點:降低了程序的運行效率(所以儘量減少使用同步)
JDK1.5中提供了多線程升級解決方案:
將同步替換成Lock操作,將notify(), notifyAll(), wait()替換成了Condition對象(通過Lock獲取)
四,死鎖:
原因:同步代碼塊代碼塊或函數中嵌套同步,並且兩個同步的鎖不相同
示例代碼:
public class Test3 {
public static void main(String[] args) {
DeadLock td1 = new DeadLock();
DeadLock td2 = new DeadLock();
td1.flag = 1;
td2.flag = 0;
new Thread(td1).start();
new Thread(td2).start();
}
}
class DeadLock implements Runnable {
public int flag = 1;
static Object o1 = new Object(), o2 = new Object();
@Override
public void run() {
System.out.println("flag=" + flag);
if (flag == 1) {
synchronized (o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o2) {
System.out.println("1");
}
}
}
if (flag == 0) {
synchronized (o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o1) {
System.out.println("0");
}
}
}
}
}
五,線程的生命週期
六,線程常用方法:
currentThread()
返回對當前正在執行的線程對象的引用
getName()
返回該線程的名稱
getPriority()
返回線程的優先級。
getState()
返回該線程的狀態。
interrupt()
中斷線程。
interrupted()
測試當前線程是否已經中斷。
isDaemon()
測試該線程是否爲守護線程
run()
如果該線程是使用獨立的Runnable
運行對象構造的,則調用該Runnable
對象的run
方法;否則,該方法不執行任何操作並返回。
setName(String name)
改變線程名稱,使之與參數name
相同。
setPriority(int newPriority)
更改線程的優先級。
sleep(long millis)
在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和準確性的影響。
start()
使該線程開始執行;Java 虛擬機調用該線程的run
方法。
toString()
返回該線程的字符串表示形式,包括線程名稱、優先級和線程組。
yield()
暫停當前正在執行的線程對象,並執行其他線程。
七,notify(),notifyAll(),wait():
都使用在同步代碼塊中,因爲要對持有監視器(鎖)的線程操作,只有同步纔有鎖
注:等待和喚醒必須是同一個鎖
八,線程的中斷和恢復:
中斷:線程在調用 Object 類的 wait()、wait(long)或 wait(long,int) 方法,或者該類的join()、join(long)、join(long,int)、sleep(long)或 sleep(long,int) 方法過程中受阻
恢復:線程調用interrupt()方法
九,守護線程:依賴非守護線程存在,當非守護線程結束以後,守護線程自動結束,可以通過setDaemon(true)將線程設爲守護線程