java中的多線程是一個同時執行多個線程的進程,線程是一個輕量級的子進程,是最小的處理單位。線程是進程的一條執行路徑,
而進程是線程的集合。
1.優點:
① 他不會阻塞用戶,因爲線程是獨立的,可以同時執行多個操作。
② 可以一起執行許多操作,因此可以節省時間。(提高程序效率)
③ 線程是獨立的,因此如果單個線程中發生異常,他不會影響其他線程。
2.多任務處理
多任務處理是同時執行多個任務的過程。使用多任務來利用CPU,多任務處理可以通過兩種方式來實現:
① 基於進程的多任務處理(多進程)
特點:每個進程在內存中都單獨分配有一個內存區域,進程是重量級的。進程之間的通信成本很高。從
一個進程切換到另一個進程需要一些時間來保存和加載寄存器、內存映射、更新列表等。
② 基於線程的多任務處理 (多線程)
特點:線程共享相同的地址空間;線程之間是輕量級的;線程之間的通信成本很低。
3.Thread類
java提供了Thread類來實現線程編程。Thread類提供了在線程上創建和執行操作的構造函數和方法。Thread類
擴展了object類並實現了runnable接口。
創建線程的方式: MyThread myThread = new MyThread();
4.runnable接口
創建線程有兩種方式,一種是直接繼承Thread類,另外一種是實現runnable接口。相比較Thread而言,通過實現
runnable的方式可以更容易地實現資源共享,並且接口可以多實現且還能再繼承其他類。
總結:① 適合多個相同的程序代碼的線程去處理同一個資源
② 可以java中單繼承的限制
③ 增加程序的健壯性,代碼可以被多個線程共享,代碼和數據獨立。
創建線程的方式: MyThread myThread = new MyThread(); //只需要創建一個實例化對象然後被多個線程使用
Thread Thread1 = new Thread(myThread); //線程1
Thread Thread2 = new Thread(myThread); //線程2
5.線程生命週期
① 新建狀態:通過new創建一個線程,跟其他對象的創建時一樣的。此時虛擬機會爲其分配內存,並初始化
其成員變量的值。
② 就緒狀態:當線程對象調用了start方法之後,線程就進入了就緒狀態。程序就會爲其創建方法調用棧和程
序計數器,處於這個狀態中的線程並沒有開始運行,只是表示該線程可以運行了,至於何時運
行,取決於jvm中的線程調度器的調度。
③ 運行狀態:當處於就緒狀態的線程獲得cpu,開始執行run()方法的線程執行體時,線程就進入了運行狀態,
線程調度的細節取決於底層平臺採用的策略(搶佔式調度策略和協作式調度策略)
④ 阻塞狀態:運行狀態的線程遇到以下情況就會進入阻塞狀態:
1.線程自己調用sleep方法主動放棄處理器資源;
2.該線程調用了一個阻塞式IO方法,在該方法返回之前,該線程處於阻塞狀態。
3.該線程試圖獲得一個同步監視器,但該同步監視器正被其他線程持有。
4.線程正在等待某個通知(notify)
5.程序調用了線程的suspend方法,將線程掛起(容易導致死鎖,避免使用)
⑤ 死亡狀態:有三種情況會使線程進入死亡狀態:
1.run方法執行完成,線程正常結束。
2.線程拋出未被捕獲的exception或者error
3.人爲停止,比如調用stop方法(暴力停止,不建議使用),以及其他停止策略。
6.線程中常用的方法
package com.multithreading.test;
//創建線程類,方法一
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String threadName,ThreadGroup tg) {
super(tg,threadName);
start();
}
//線程功能函數
public void run() {
for(int i=1;i<=5;i++) {
try {
Thread.sleep(500);
} catch (Exception e) {
System.out.println(e.toString());
}
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
public static void main(String[] args) throws InterruptedException {
//創建線程的方式1
MyThread myThread = new MyThread();
myThread.start();
myThread.interruptAndIsInterruptedAndInterrupted();
//創建線程的方式2
MyThread3 MyThread3 = new MyThread3();
//線程1
Thread t1 = new Thread(MyThread3);
t1.start();
//線程2
Thread t2 = new Thread(MyThread3);
t2.start();
}
//1. start() 啓動線程 線程方法
public static void starts() {
MyThread myThread= new MyThread();
myThread.start();
}
//2. run() 執行線程 線程方法
public static void runs() {
//開啓線程之後,會自動運行run方法執行線程代碼功能。如上上
MyThread myThread= new MyThread();
myThread.start();
}
//3. sleep() 指定的時間內休眠線程
public static void sleep() throws InterruptedException {
MyThread myThread= new MyThread();
myThread.start();
myThread.sleep(1000); //休眠一秒鐘(多線程中不會釋放對象鎖,與wait的比較)
}
//currentThread() 返回對當前正在執行線程對象的引用 線程方法
public static void currentThreads() {
MyThread myThread= new MyThread();
myThread.setName("我是MyThread");
myThread.start();
Thread t = Thread.currentThread(); //主線程
System.out.println(myThread.getName());
}
//join() 實現線程的執行順序 線程方法
public static void joins() {
MyThread myThread1= new MyThread();
myThread1.setName("myThread1");
MyThread myThread2= new MyThread();
myThread2.setName("myThread2");
MyThread myThread3= new MyThread();
myThread3.setName("myThread3");
myThread1.start();
try {
myThread1.join(1500); //myThread1優先執行1500毫秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myThread2.start();
myThread3.start();
}
//setpriority() 設置線程優先級(1-10,默認爲5,數字越大優先級越高,但不代表級別越高就一定優先執行,只是優先執行的概率更大)
//getPriority() 返回線程優先級級別
//另外還有三個常規優先級屬性 MIN_PRIORITY設置最小優先級,值爲1 MAX_PRIORITY設置最大優先級,值爲10 NORM_PRIORITY普通優先級值爲5
public static void setPriorityAndGetPriority() {
MyThread myThread1= new MyThread();
MyThread myThread2= new MyThread();
myThread1.setPriority(1);
myThread1.setName("myThread1");
System.out.println(myThread1.getPriority());
myThread2.setPriority(9);
myThread2.setName("myThread2");
System.out.println(myThread2.getPriority());
myThread1.start();
myThread2.start();
//myThread1.setPriority(Thread.MIN_PRIORITY);
//myThread1.setPriority(Thread.MAX_PRIORITY);
//myThread1.setPriority(Thread.NORM_PRIORITY);
}
//setName() 設置線程名稱
//getName() 獲取線程名稱
public static void setNameAndGetName() {
//以上方法中已經多次應用
}
//返回線程編號
public static void geId() {
MyThread myThread= new MyThread();
myThread.getId();
System.out.println(myThread.getId());
}
//isAlive() 測試線程是否活着 線程方法
public static void isAlives() {
MyThread myThread= new MyThread();
myThread.start();
System.out.println(myThread.isAlive());
}
//yield() Thread類的yield()方法導致當前正在執行的線程對象暫停並允許其他線程執行(其實就是降低優先級,但不代表不會先執行)
public static void yield() {
MyThread myThread1= new MyThread();
myThread1.setName("myThread1");
MyThread myThread2= new MyThread();
myThread2.setName("myThread2");
myThread1.start();
myThread2.start();
for(int i=0;i<3;i++) {
//如果myThread1線程正在執行,則執行該方法,意味着自己不運行run,重新回到就緒狀態與其他線程一同競爭cpu時間
myThread1.yield();
System.out.println(myThread1.getName()+":我們一同競爭吧");
}
}
//stop() 暴力停止線程,強制中斷線程的執行。容易造成數據不一致,屬於不安全的方法,包括suspend()(阻塞線程) resume()(恢復線程) 等已經棄用
public static void stops() {
//略
}
//destroy() 銷燬線程組以及子線程組
//ThreadGroup 線程組類,管理線程的類,即線程組就是由線程組成的管理線程的類,這個類是java.lang.ThreadGroup類
public static void destroys() throws InterruptedException {
//創建一個名爲Parent thread的線程組
ThreadGroup g1 = new ThreadGroup("Parent thread");
//創建一個名爲Child thread的線程組
ThreadGroup g2 = new ThreadGroup("Child thread");
//在線程組中創建線程,在有參構造函數已經啓動了線程
MyThread myThread1= new MyThread("myThread1",g1);
MyThread myThread2= new MyThread("myThread2",g2);
myThread1.join();
myThread2.join();
g1.destroy();
System.out.println(g1.getName()+" is destoried");
g2.destroy();
System.out.println(g2.getName()+" is destoried");
}
// isDaemon() 該線程是否是一個守護線程
// setDaemon() 將線程標記爲守護線程或用戶線程
public static void isDaemons() {
MyThread myThread= new MyThread();
System.out.println(myThread.isDaemon());
myThread.setDaemon(true);
System.out.println(myThread.isDaemon());
//守護線程與用戶線程(非守護線程)
//守護線程是爲用戶線程服務的,比如垃圾回收線程,非必要線程。當所有的非守護線程結束時,程序也就終止了,同時會殺死進程中的所有守護線程
//用戶線程就是執行業務功能代碼的線程。
}
//interrupt() 標記需要中斷的線程,中斷的執行由具體實現代碼決定
//isInterrupted() 用來判斷當前線程的中斷狀態
//interrupted() 此方法清除線程的中斷狀態,這意味着如果要連續兩次調用此方法,則第二次調用將返回false。 如果線程的中斷狀態爲true,則此方法將狀態設置爲false
public void interruptAndIsInterruptedAndInterrupted() {
MyThread2 myThread= new MyThread2();
myThread.start();
System.out.println(myThread.isAlive());
myThread.interrupt();
System.out.println(myThread.isAlive());
}
class MyThread2 extends Thread{
public void run() {
for(int i=1;i<=5;i++) {
try {
//爲true時,說明被標記爲需要中斷的線程,然後通過return直接返回來實現中斷線程
if(Thread.currentThread().isInterrupted()) {
return;
}
} catch (Exception e) {
System.out.println(e.toString());
}
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
//notify() 隨機喚醒wait等待池中的線程,從而可以去競爭獲取對象鎖
//notifyAll() 喚醒所有wait等待池中的線程
public static void notifyAndNotifyAll() {
//略
}
//wait 使線程進行阻塞狀態,並且會釋放鎖
public static void waits() {
//略
}
}
//創建線程方法2,實現rnnable接口
class MyThread3 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
}
}