JAVA多線程淺析

什麼是多線程

Java 給多線程編程提供了內置的支持。 一條線程指的是進程中一個單一順序的控制流,一個進程中可以併發多個線程,每條線程並行執行不同的任務。

多線程是多任務的一種特別的形式,但多線程使用了更小的資源開銷。

這裏定義和線程相關的另一個術語 - 進程:一個進程包括由操作系統分配的內存空間,包含一個或多個線程。一個線程不能獨立的存在,它必須是進程的一部分。一個進程一直運行,直到所有的非守護線程都結束運行後才能結束。

多線程能滿足程序員編寫高效率的程序來達到充分利用 CPU 的目的。

如何使用

繼承Thread類創建線程

 

/**
 * 多線程實現的第一種方法,繼承Thread 
 *
 */

//1.自定義一個類,繼承java.lang包下的Thread類
class MyThread extends Thread {
    //2.重寫run方法
    public void run() {        
        //3.將要在線程中執行的代碼編寫在run方法中
        for(int i = 0; i < 1000; i++) {        
            System.out.println("monkey");
        }
    }
}

public class ThreadTest01 extends Thread {

    public static void main(String[] args) {
        //4.創建上面自定義類的對象
        //創建一個線程
        MyThread mt = new MyThread();        

        //5.調用start方法啓動線程
        mt.start();                            

        //將循環的次數設置多一些,否則還沒等到CPU切換就已經打印完成了
        for(int i = 0; i < 1000; i++) {
            System.out.println("1024");
        }
    }

}

實現Runnable接口創建線程

/**
 * 多線程實現的第二種方法,實現Runnable接口
 *
 */

// 1.自定義一個類實現java.lang包下的Runnable接口
class MyRunnable implements Runnable {

    // 2.重寫run方法
    @Override
    public void run() {
        // 3.將要在線程中執行的代碼編寫在run方法中
        for (int i = 0; i < 1000; i++) {
            System.out.println("monkey");
        }
    }

}

public class ThreadTest02 {

    public static void main(String[] args) {
        // 4.創建上面自定義類的對象
        MyRunnable mr = new MyRunnable();

        // 5.創建Thread對象並將上面自定義類的對象作爲參數傳遞給Thread的構造方法
        Thread t = new Thread(mr); 

        //6.調用start方法啓動線程
        t.start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("1024");
        }
    }

}

實現Callable接口創建線程

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 多線程實現的第三種方法,實現Callable接口 優點: 可以獲取返回值 可以拋出異常
 */

//1.定義一個類實現Callable<V>接口
class MyCallable implements Callable<Integer> {

    //睡眠時間
    private long second;

    //計算階乘
    private int count;

    public MyCallable(int count, long second) {
        this.count = count;
        this.second = second;
    }

    // 2.重寫call方法
    @Override
    public Integer call() throws Exception {
        // 3.將要執行的代碼寫在call方法中
        // 計算階乘
        //讓當前線程睡眠,單位是毫秒
        Thread.sleep(second);
        int sum = 1;

        if (count == 0) {
            sum = 0;
        } else {
            for (int i = 1; i <= count; i++) {
                sum *= i;
            }
        }

        // 打印線程名稱
        System.out.println(Thread.currentThread().getName() + "-----sum=" + sum);

        return sum;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

}

public class ThreadTest03 {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //4.創建ExecutorService線程池
        ExecutorService exec = Executors.newCachedThreadPool();

        //5.創建存儲Future對象的集合,用來存放ExecutorService的執行結果
        ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>();

        //6.開啓2個線程,將返回的Future對象放入集合中
        for (int i = 0; i < 2; i++) {
            if (i == 0) {
                //計算5的階乘,睡眠10秒
                results.add(exec.submit(new MyCallable(5, 10000)));
            } else {
                //計算3的階乘,睡眠i秒
                results.add(exec.submit(new MyCallable(3, i)));
            }
        }


        for (Future<Integer> fs : results) {
            //7.判斷線程是否執行結束,如果執行結束就將結果打印
            if (fs.isDone()) {
                System.out.println("計算結果:" + fs.get());
            } else {
                System.out.println(fs.toString() + "該線程還沒有計算完畢,請耐心等待");
            }
        }

        //8.關閉線程池,不再接收新的線程,未執行完的線程不會被關閉
        exec.shutdown();
        System.out.println("main方法執行結束");
    }

}

三種實現方式的比較

  • 繼承Thread
    • 優點:可以直接使用Thread類中的方法,代碼簡單
    • 缺點:繼承Thread類之後就不能繼承其他的類
  • 實現Runnable接口
    • 優點:即時自定義類已經有父類了也不受影響,因爲可以實現多個接口
    • 缺點: 在run方法內部需要獲取到當前線程的Thread對象後才能使用Thread中的方法
  • 實現Callable接口
    • 優點:可以獲取返回值,可以拋出異常
    • 缺點:代碼編寫較爲複雜
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章