Java線程:線程的創(chuàng)建

線程的創(chuàng)建

  1. Java語(yǔ)言的JVM允許程序運(yùn)行多個(gè)線程,它通過(guò)java.lang.Thread 類來(lái)體現(xiàn)。
  2. Thread類的特性 :
    • 每個(gè)線程都是通過(guò)某個(gè)特定Thread對(duì)象的run()方法來(lái)完成操作的,經(jīng)常把run()方法的主體稱為線程體。
    • 通過(guò)該Thread對(duì)象的start()方法來(lái)啟動(dòng)這個(gè)線程,而非直接調(diào)用run()。

方式一:繼承Thread類

  1. 定義子類繼承Thread類。
  2. 子類中重寫(xiě)Thread類中的run()方法。
  3. 創(chuàng)建Thread子類對(duì)象,即創(chuàng)建了線程對(duì)象。
  4. 調(diào)用線程對(duì)象start()方法:?jiǎn)?dòng)線程,調(diào)用run()方法。

示例代碼:

public class ThreadDemo {

    public static void main(String[] args) {
        
        MyThread mythread = new MyThread();
        mythread.start();
        
        for (int i = 0; i < 10; i++)
            System.out.println("The thread 0 is running.");
        
    }
}

class MyThread extends Thread {
    public MyThread() {
        super();
    }

    public void run() {

        for (int i = 0; i < 10; i++)
            System.out.println("The thread 1 is running.");
    }
}

輸出:

The thread 1 is running.
The thread 1 is running.
The thread 1 is running.
The thread 1 is running.
The thread 1 is running.
The thread 1 is running.
The thread 1 is running.
The thread 1 is running.
The thread 1 is running.
The thread 0 is running.
The thread 0 is running.
The thread 0 is running.
The thread 0 is running.
The thread 0 is running.
The thread 0 is running.
The thread 0 is running.
The thread 0 is running.
The thread 0 is running.
The thread 0 is running.
The thread 1 is running.

方式二:實(shí)現(xiàn)Runnable接口

  1. 定義子類,實(shí)現(xiàn)Runnable接口。
  2. 子類中重寫(xiě)Runnable接口中的run()方法。
  3. 通過(guò)Thread類含參構(gòu)造器創(chuàng)建線程對(duì)象。
  4. 將Runnable接口的子類對(duì)象作為實(shí)際參數(shù)傳遞給Thread類的構(gòu)造器中。
  5. 調(diào)用Thread類的start()方法:開(kāi)啟線程,調(diào)用Runnable子類接口的run()方法。
public class ThreadDemo {

    public static void main(String[] args) {

        MyThread1 myThread1 = new MyThread1();
        Thread t1 = new Thread(myThread1);
        Thread t2= new Thread(myThread1);
        t1.start();
        t2.start();

        for (int i = 0; i < 10; i++)
            System.out.println(String.format("%s : is running.", Thread.currentThread().getName()));

    }
}
public class MyThread1 extends Thread implements Runnable {

    public void run() {
        for (int i = 0; i < 10; i++)
            System.out.println(String.format("%s : is running.", Thread.currentThread().getName()));
    }
}

Thread-1 : is running.
main : is running.
Thread-1 : is running.
Thread-2 : is running.
Thread-1 : is running.
main : is running.
Thread-1 : is running.
main : is running.
Thread-2 : is running.
Thread-1 : is running.
Thread-2 : is running.

繼承方式和實(shí)現(xiàn)方式的聯(lián)系與區(qū)別:

public class Thread extends Object implements Runnable
  • 區(qū)別
    1. 繼承Thread:線程代碼存放Thread子類run()方法中。
    2. 實(shí)現(xiàn)Runnable:線程代碼存在接口的子類的run()方法。
  • 實(shí)現(xiàn)方式的好處
    1. 避免了單繼承的局限性 。
    2. 多個(gè)線程可以共享同一個(gè)接口實(shí)現(xiàn)類的對(duì)象,非常適合多個(gè)相同線程來(lái)處理同一份資源。

方式三: 實(shí)現(xiàn)Callable接口

與Runnable相比

  • 相比run()方法,可以有返回值
  • 方法可以拋出異常
  • 支持泛型的返回值
  • 需要借助FutureTask類,比如獲取返回結(jié)果

Future接口

  • 可以對(duì)具體Runnable、Callable任務(wù)的執(zhí)行結(jié)果進(jìn)行取消、查詢是否完成、獲取結(jié)果等。
  • FutrueTask是Futrue接口的唯一的實(shí)現(xiàn)類
  • FutureTask 同時(shí)實(shí)現(xiàn)了Runnable, Future接口。它既可以作為Runnable被線程執(zhí)行,又可以作為Future得到Callable的返回值

方式四:使用線程池

背景:

經(jīng)常創(chuàng)建和銷毀、使用量特別大的資源,比如并發(fā)情況下的線程, 對(duì)性能影響很大.

思路:

提前創(chuàng)建好多個(gè)線程,放入線程池中,使用時(shí)直接獲取,使用完放回池中??梢员苊忸l繁創(chuàng)建銷毀、實(shí)現(xiàn)重復(fù)利用。類似生活中的公共交通工具。

優(yōu)點(diǎn):

提高響應(yīng)速度(減少了創(chuàng)建新線程的時(shí)間)
降低資源消耗(重復(fù)利用線程池中線程,不需要每次都創(chuàng)建)
便于線程管理

示例代碼:

import java.util.concurrent.*;

public class ThreadCallable {

    public static void main(String[] args) {
        CounterTen ct = new CounterTen();
        FutureTask ft = new FutureTask(ct);
        new Thread(ft).start();

        try {
            System.out.println(ft.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

class CounterTen implements Callable {

    @Override
    public Object call() throws Exception {
        int[] s = new int[10];
        for (int i = 0; i < 10; i++) {

            s[i] = i;
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName() + " " + i);

        }

        return s;
    }

}

輸出:

Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
[I@1e643faf

線程池相關(guān)API

JDK5.0起提供了線程池相關(guān)API:ExecutorService和Executors

  • ExecutorService:真正的線程池接口。常見(jiàn)子類ThreadPoolExecutor
    • void execute(Runnable command):執(zhí)行任務(wù)/命令,沒(méi)有返回值,一般用來(lái)執(zhí)行Runnable
    • <T>Future<T> submit(Callable<T> task):執(zhí)行任務(wù),有返回值,一般又來(lái)執(zhí)行Callable
    • void shutdown():關(guān)閉連接池
  • Executors:工具類、線程池的工廠類,用于創(chuàng)建并返回不同類型的線程池
    • Executors.newCachedThreadPool():創(chuàng)建一個(gè)可根據(jù)需要?jiǎng)?chuàng)建新線程的線程池
    • Executors.newFixedThreadPool(n);創(chuàng)建一個(gè)可重用固定線程數(shù)的線程池
    • Executors.newSingleThreadExecutor():創(chuàng)建一個(gè)只有一個(gè)線程的線程池
    • Executors.newScheduledThreadPool(n):創(chuàng)建一個(gè)線程池,它可安排在給定延遲后運(yùn)行命令或者定期地執(zhí)行。

示例代碼:

import java.util.concurrent.*;

public class ThreadPool {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService es = Executors.newFixedThreadPool(10);
        ShowOdd so = new ShowOdd();
        ShowEven se = new ShowEven();
        es.execute(so);
        FutureTask ft = new FutureTask(se);

        es.submit(ft);
        Object obj =ft.get();
        System.out.println(obj);
        es.shutdown();
    }
}

class ShowOdd implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 1) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

class ShowEven implements Callable {
    private int[] s = new int[5];

    @Override
    public Object call() throws Exception {
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                s[i/2] = i;
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }

        }
        return s;
    }
}

輸出:

pool-1-thread-1: 1
pool-1-thread-2: 0
pool-1-thread-2: 2
pool-1-thread-1: 3
pool-1-thread-2: 4
pool-1-thread-1: 5
pool-1-thread-2: 6
pool-1-thread-1: 7
pool-1-thread-1: 9
pool-1-thread-2: 8
[I@2812cbfa
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容