目錄

併發程式設計(一)多執行緒基礎

1、程序和執行緒的概念

  • 程序:一個應用程式,在程序中會有N多個執行緒,程序是所有執行緒的集合。

  • 執行緒:一條執行路徑。

2、為什麼要使用多執行緒

可以提高程式執行的效率。

3、多執行緒使用的場景

  1. 給使用者傳送簡訊,防止呼叫簡訊介面耗時過長
  2. 打包圖片壓縮包

4、多執行緒建立方式

4.1、繼承Thread類

package com.fly.thread_demo.demo_1;

/**
 * 執行緒建立方式一: 繼承Thread類 重寫run方法
 */
public class ThreadDemo_1 extends Thread{
    @Override
    public void run() {
        System.out.println("子執行緒開始");
        for (int i = 0; i < 10; i++) {
            System.out.println("i = " + i);
        }
        System.out.println("子執行緒結束");
    }

    public static void main(String[] args) {
        System.out.println("主執行緒開始");
        Thread t1 = new ThreadDemo_1();
        t1.start();
        System.out.println("主執行緒結束");
    }
}

4.2、實現Runable介面

package com.fly.thread_demo.demo_1;
/**
 * 執行緒建立方式二: 實現Runnable介面  
 */
public class ThreadDemo_2 implements Runnable{
    @Override
    public void run() {
        System.out.println("子執行緒開始");
        for (int i = 0; i < 10; i++) {
            System.out.println("i = " + i);
        }
        System.out.println("子執行緒結束");
    }

    public static void main(String[] args) {
        System.out.println("主執行緒開始");
        //在Thread構造方法中  接受一個Runnable介面
        Thread t2 = new Thread(new ThreadDemo_2());
        t2.start();
        System.out.println("主執行緒結束");
    }
}

4.3、匿名內部類

package com.fly.thread_demo.demo_1;

/**
 * 執行緒建立方式三: 匿名類部類
 */
public class ThreadDemo_3 {

    public static void main(String[] args) {
        System.out.println("主執行緒開始");
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("子執行緒開始");
                for (int i = 0; i < 10; i++) {
                    System.out.println("i = " + i);
                }
                System.out.println("子執行緒結束");
            }
        });
        t3.start();
        System.out.println("主執行緒結束");
    }
}

4.4、執行緒池(後面細說)

5、執行緒的聲生命週期

5.1、新建

​ new Thread();

5.2、就緒

​ 呼叫start方法後,執行run方法前,等待cpu分配資源

5.3、執行

​ 執行run方法

5.4、阻塞

  1. 呼叫sleep方法
  2. 呼叫阻塞式IO
  3. 呼叫wait方法

5.5、死亡

  1. run方法執行完畢
  2. 丟擲異常
  3. 呼叫stop方法 (容易造成死鎖,不推薦使用)

6、守護執行緒

package com.fly.thread_demo.demo_1;

/**
 * 非守護執行緒:主執行緒死亡,不影響  非守護執行緒
 * 守護執行緒:主執行緒死亡,守護執行緒同時死亡
 */
public class ThreadDemo_4 implements Runnable{
    @Override
    public void run() {
        System.out.println("子執行緒開始");
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("i = " + i);
        }
        System.out.println("子執行緒結束");
    }

    public static void main(String[] args) {
        System.out.println("主執行緒開始");
        Thread t4 = new Thread(new ThreadDemo_4());
        t4.setDaemon(true);//把t4設定為守護執行緒 (可以對比  設定和設定的區別)
        t4.start();
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("主執行緒結束");
    }
}

7、join方法

package com.fly.thread_demo.demo_1;

/**
 *  join :
 *      1) 執行緒同步,是並行的執行緒程式設計序列,在A執行緒中呼叫了B執行緒的join()方法時,表示只有當B執行緒執行完畢時,A執行緒才能繼續執行
 *      2) 在start方法呼叫之後呼叫
 *      3) 實現原理:呼叫執行緒的wait方法來達到同步的目的
 */
public class ThreadDemo_5 {

    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 30; i++) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("子執行緒i = " + i);
                }
            }
        });

        t1.start();
        try {
            //(可以對比  設定和設定列印結果的區別)
            t1.join(); //在主執行緒中呼叫t1的join方法   表示讓t1先執行完畢再執行主執行緒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("主i = " + i);
        }
    }
}
package com.fly.thread_demo.demo_1;

/**
 * 面試題  現在有3個執行緒 t1 ,t2,t3   如何讓t1 執行完畢 再執行 t2  t2執行完畢再執行t3
 */
public class ThreadDemo_6 {

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("t1:i = " + i);
                }
            }
        });
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    t1.join();//t2 中 呼叫 t1.join() :讓t1執行完畢執行t2
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (int i = 0; i < 10; i++) {
                    System.out.println("t2:i = " + i);
                }
            }
        });
        t2.start();

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    t2.join();//t3中 呼叫 t2.join() :讓t2執行完畢執行t3
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (int i = 0; i < 10; i++) {
                    System.out.println("t3:i = " + i);
                }
            }
        });
        t3.start();
    }
}