1. 程式人生 > 程式設計 >併發程式設計之多執行緒(Java)

併發程式設計之多執行緒(Java)

一、執行緒與程式區別

每個正在系統上執行的程式都是一個程式。每個程式包含一到多個執行緒。執行緒是一組指令的集合,或者是程式的特殊段,它可以在程式裡獨立執行。也可以把它理解為程式碼執行的上下文。所以執行緒基本上是輕量級的程式,它負責在單個程式裡執行多工。通常由作業系統負責多個執行緒的排程和執行

使用執行緒可以把佔據時間長的程式中的任務放到後臺去處理,程式的執行速度可能加快,在一些等待的任務實現上如使用者輸入、檔案讀寫和網路收發資料等,執行緒就比較有用了。在這種情況下可以釋放一些珍貴的資源如記憶體佔用等等。

如果有大量的執行緒,會影響效能,因為作業系統需要在它們之間切換,更多的執行緒需要更多的記憶體空間,執行緒的中止需要考慮其對程式執行的影響。通常塊模型資料是在多個執行緒間共享的,需要防止執行緒死鎖情況的發生。

總結:程式是所有執行緒的集合,每一個執行緒是程式中的一條執行路徑。

二、為什麼要使用多執行緒?

多執行緒提高程式執行效率。如: 迅雷多執行緒下載、資料庫連線池、分批傳送簡訊等。

三、多執行緒建立方式

1、第一種繼承Thread類 重寫run方法

/**
 * 
 * @classDesc: 功能描述:(建立多執行緒例子-Thread類 重寫run方法)
 */
class CreateThread extends Thread {
    // run方法中編寫 多執行緒需要執行的程式碼
    public void run() {
        for (inti = 0; i< 10; i++) {
            System.out.println("i:" + i);
        }
    }
}
public class ThreadDemo {

    public static void main(String[] args) {
        System.out.println("-----多執行緒建立開始-----");
        // 1.建立一個執行緒
        CreateThread createThread = new CreateThread();
        // 2.開始執行執行緒 注意 開啟執行緒不是呼叫run方法,而是start方法
        System.out.println("-----多執行緒建立啟動-----");
        createThread.start();
        System.out.println("-----多執行緒建立結束-----");
    }

}複製程式碼

2、第二種實現Runnable介面,重寫run方法

/**
 * 
 * @classDesc: 功能描述:(建立多執行緒例子-Thread類 重寫run方法)
 */
class CreateRunnable implements Runnable {

    @Override
    publicvoid run() {
        for (inti = 0; i< 10; i++) {
            System.out.println("i:" + i);
        }
    }

}

/**
 * 
 * @classDesc: 功能描述:(實現Runnable介面,重寫run方法)
 */
public class ThreadDemo2 {
    public static void main(String[] args) {
        System.out.println("-----多執行緒建立開始-----");
        // 1.建立一個執行緒
        CreateRunnable createThread = new CreateRunnable();
        // 2.開始執行執行緒 注意 開啟執行緒不是呼叫run方法,而是start方法
        System.out.println("-----多執行緒建立啟動-----");
        Thread thread = new Thread(createThread);
        thread.start();
        System.out.println("-----多執行緒建立結束-----");
    }
}複製程式碼

3、第三種使用匿名內部類方式

public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i< 10; i++) {
                    System.out.println("i:" + i);
                }
            }
        });
         thread.start();
    }
}
複製程式碼

四、常用APi

使用繼承Thread類還是使用實現Runnable介面好?

使用實現實現Runnable介面好,原因實現了介面還可以繼續繼承,繼承了類不能再繼承。

獲取執行緒物件以及名稱

常用執行緒api方法

start() 啟動執行緒

currentThread() 獲取當前執行緒物件

getID() 獲取當前執行緒ID Thread-編號  該編號從0開始

getName() 獲取當前執行緒名稱

sleep(long mill) 休眠執行緒

Stop() 停止執行緒,

常用執行緒建構函式

Thread() 分配一個新的 Thread 物件

Thread(String name) 分配一個新的 Thread物件,具有指定的 name正如其名。

Thread(Runable r) 分配一個新的 Thread物件

Thread(Runable r,String name) 分配一個新的 Thread物件

五、守護執行緒

Java中有兩種執行緒,一種是使用者執行緒,另一種是守護執行緒。

使用者執行緒是指使用者自定義建立的執行緒,主執行緒停止,使用者執行緒不會停止

守護執行緒當程式不存在或主執行緒停止,守護執行緒也會被停止。

使用setDaemon(true)方法設定為守護執行緒

thread.setDaemon(true)

六、join()方法作用

當在主執行緒當中執行到t1.join()方法時,就認為主執行緒應該把執行權讓給t1

 Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {

                    }
                    System.out.println(Thread.currentThread().getName() + "i:" + i);
                }
            }
        });
        t1.start();
        // 當在主執行緒當中執行到t1.join()方法時,就認為主執行緒應該把執行權讓給t1
        t1.join();
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(10);
            } catch (Exception e) {

            }
            System.out.println("main" + "i:" + i);
        }複製程式碼

七、優先順序

現代作業系統基本採用時分的形式排程執行的執行緒,執行緒分配得到的時間片的多少決定了執行緒使用處理器資源的多少,也對應了執行緒優先順序這個概念。在JAVA執行緒中,通過一個int priority來控制優先順序,範圍為1-10,其中10最高,預設值為5。下面是原始碼(基於1.8)中關於priority的一些量和方法。

class PrioritytThread implements Runnable {

    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().toString() + "---i:" + i);
        }
    }
}

/**
 * 
 * @classDesc: 
 */
public class ThreadDemo4 {

    public static void main(String[] args) {
        PrioritytThread prioritytThread = new PrioritytThread();
        Thread t1 = new Thread(prioritytThread);
        Thread t2 = new Thread(prioritytThread);
        t1.start();
        // 注意設定了優先順序, 不代表每次都一定會被執行。 只是CPU排程會有限分配
        t1.setPriority(10);
        t2.start();
        
    }

}複製程式碼

八、Yield方法

Thread.yield()方法的作用:暫停當前正在執行的執行緒,並執行其他執行緒。(可能沒有效果)yield()讓當前正在執行的執行緒回到可執行狀態,以允許具有相同優先順序的其他執行緒獲得執行的機會。因此,使用yield()的目的是讓具有相同優先順序的執行緒之間能夠適當的輪換執行。但是,實際中無法保證yield()達到讓步的目的,因為,讓步的執行緒可能被執行緒排程程式再次選中。結論:大多數情況下,yield()將導致執行緒從執行狀態轉到可執行狀態,但有可能沒有效果。