1. 程式人生 > >Java多執行緒(一):執行緒與程序

Java多執行緒(一):執行緒與程序

1.執行緒和程序

1.1 程序

程序是作業系統的概念,我們執行的一個TIM.exe就是一個程序。

程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。在早期面向程序設計的計算機結構中,程序是程式的基本執行實體;在當代面向執行緒設計的計算機結構中,程序是執行緒的容器。程式是指令、資料及其組織形式的描述,程序是程式的實體

1.2 執行緒

執行緒是依附於程序而存在的,每一個執行緒必須有父程序;
執行緒擁有自己的堆疊、程式計數器和區域性變數,執行緒和其他的執行緒共享程序的系統資源;
程序不能共享記憶體,而執行緒之間可以輕鬆地共享記憶體

2.多執行緒的意義

2.1 發揮多核處理器最大效能

如一個四核處理器去執行單執行緒任務,一個核心只能執行一個執行緒,那麼三個核心的效能就會被浪費。再如伺服器32核CPU執行一個單執行緒任務,31個核心在“偷懶”,大大地浪費了伺服器效能;
比如博主的電腦CPU是i7 6700HQ,四核八執行緒。該CPU用到了超執行緒技術。簡單地說,一個單核心的處理器,去模擬出雙核心的環境,但這並非能夠把處理器的效能提升雙倍,原因在於實體的核心始終只有一個,而效能有約百分之二十至三十增長。
我們可以理解成閹割版八核處理器,難道買不起八核,還買不起八執行緒處理器嗎?

2.2 發揮單核處理器最大效能

如果程序是單執行緒的,它在等待某個I/O操作完成,此時處理器處於空閒狀態;如果程序是多執行緒的,一個執行緒在等待某個I/O操作完成的時候,另外一個執行緒可以執行。

單核處理器執行多執行緒的情況

1.單核CPU同一時間,CPU只能處理1個執行緒,只有1個執行緒在執行
2.多執行緒同時執行:是CPU快速的在多個執行緒之間的切換
3.CPU排程執行緒的時間足夠快,使我們產生錯覺,多執行緒“同時”執行
4.如果執行緒數非常多,CPU會在n個執行緒之間切換,消耗大量的CPU資源,每個執行緒被排程的次數會降低,執行緒的執行效率降低

3.建立執行緒

3.1 繼承Thread

繼承Thread,重寫run方法。

public class MyThread00 extends Thread{
    public void run()
    {
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName() + "在執行!");
        }
    }


    public static void main(String[] args)
    {
        MyThread00 mt0 = new MyThread00();
        //啟動執行緒
        mt0.start();

        //main執行緒
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName() + "在執行!");
        }
    }
}

start方法:
呼叫start方法Java虛擬機器會啟動run方法;
一個執行緒不能多次呼叫start方法;
死去的執行緒不能被重啟;
執行結果如下:

main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
main在執行!
Thread-0在執行!
Thread-0在執行!
Thread-0在執行!
Thread-0在執行!
Thread-0在執行!
Thread-0在執行!
Thread-0在執行!
Thread-0在執行!
......

執行緒交替執行,不會按照固定順序執行,每次執行的結果都不一致。

3.2 實現Runnable

實現Runnable介面,重寫run方法;有利於程式碼解耦。

public class MyThread01 implements Runnable
{
    public void run()
    {
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName() + "在執行!");
        }
    }

    public static void main(String[] args)
    {
        MyThread01 mt0 = new MyThread01();
        Thread t = new Thread(mt0);
        //啟動執行緒
        t.start();
        //main執行緒
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName() + "在執行!");
        }
    }
}

執行結果類似於3.1

3.3 實現Callable

實現Callable建立執行緒,重寫call方法,該方法可以返回值和丟擲異常

public class MyThread03 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("計算處理中...");
        Thread.sleep(3000);
        return 1;
    }

    public static void main(String[] args) {
        //構建任務
        MyThread03 t = new MyThread03();
        //執行Callable方式,需要FutureTask實現類的支援,用於接收運算結果
        FutureTask<Integer> task = new FutureTask<Integer>(t);
        //啟動執行緒
        new Thread(task).start();
        //獲取結果
        try {
            Integer integer = task.get(5000,TimeUnit.MILLISECONDS);
            System.out.println("執行緒執行結果:"+integer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

執行結果如下

計算處理中...
執行緒執行結果:1

我們獲取到了call方法的返回值,繼承Thread和實現Runnable方式建立執行緒無法獲得返回