Java:多線程,分別用Thread、Runnable、Callable實現線程


並發性(concurrency)和並行性(parallel)是兩個概念,並行是指在同一時刻,有多條指令在多個處理器上同時執行;並發指在同一時刻只能有一條指令執行,但多個進程指令被快速輪換執行,使得宏觀上具有多個進程同時執行的效果。

多線程編程優點:

  1. 進程之間不能共享內存,但線程之間共享內存非常容易。
  2. 系統創建線程所分配的資源相對創建進程而言,代價非常小。

Java中實現線程的方式目前有三種:

一:繼承Thread類創建線程類

package com.clzhang.sample.thread;

// 通過繼承Thread類來創建線程類
public class ThreadByExtends extends Thread {
    private int i;

    @Override
    public void run() {
        // 當線程類繼承Thread類時,直接使用this即可獲取當前線程句柄。
        // 因此可以直接調用getName()方法返回當前線程的名稱。
        System.out.println("當前線程名稱是:" + getName());

        for (; i < 5; i++) {
            System.out.println(getName() + ":" + i);
            try {
                // 保證讓別的線程也有執行的機會
                Thread.sleep(10);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main(String[] args) {
        // 靜態方法沒有this,只能通過Thread.currentThread獲取當前線程句柄
        System.out.println(Thread.currentThread().getName());
        
        // 創建、並啟動第一條線程
        new ThreadByExtends().start();
        // 創建、並啟動第二條線程
        new ThreadByExtends().start();
    }
}

輸出:

main
當前線程名稱是:Thread-0
Thread-0:0
當前線程名稱是:Thread-1
Thread-1:0
Thread-0:1
Thread-1:1
Thread-1:2
Thread-0:2
Thread-1:3
Thread-0:3
Thread-0:4
Thread-1:4

二:實現Runnable接口創建線程類

package com.clzhang.sample.thread;

/**
 * 通過實現Runnable接口來創建線程類
 * 1.Runnable非常適合多個相同線程來處理同一份資源的情況
 * 2.Runnable可以避免由於Java的單繼承機制帶來的局限
 * 3.如果想獲取當前線程句柄,只能用Thread.currentThread()方法
 */
public class ThreadByRunnable implements Runnable {
    private int i;

    @Override
    public void run() {
        System.out.println("當前線程名稱是:" + Thread.currentThread().getName());

        for (; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);

            try {
                // 因為sleep是靜態方法,所以不需要通過Thread.currentThread()方法獲取當前線程句柄
                Thread.sleep(10);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main(String[] args) {
        ThreadByRunnable st = new ThreadByRunnable();
        new Thread(st, "新線程1").start();
        new Thread(st, "新線程2").start();
    }
}

輸出:

當前線程名稱是:新線程1
當前線程名稱是:新線程2
新線程2:0
新線程1:0
新線程2:2
新線程1:2
新線程2:3
新線程1:4

三:使用Calable和Future創建具備返回值的線程

package com.clzhang.sample.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

// 實現Callable接口來實現線程
public class ThreadByCallable implements Callable<Integer> {
    
    @Override
    public Integer call() {
        System.out.println("當前線程名稱是:" + Thread.currentThread().getName());

        int i = 0;
        for (; i < 5; i++) {
            System.out.println("循環變量i的值:" + i);
        }
        
        // call()方法有返回值
        return i;
    }

    public static void main(String[] args) {
        ThreadByCallable rt = new ThreadByCallable();

        // 使用FutureTask來包裝Callable對象
        FutureTask<Integer> task = new FutureTask<Integer>(rt);
        new Thread(task, "有返回值的線程").start();
        try {
            // 獲取線程返回值
            System.out.println("子線程的返回值:" + task.get());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

輸出:

當前線程名稱是:有返回值的線程
循環變量i的值:0
循環變量i的值:1
循環變量i的值:2
循環變量i的值:3
循環變量i的值:4
子線程的返回值:5

總結

用Runnable與Callable接口的方式創建多線程的特點:

  1. 線程類只是實現了Runnable接口或Callable接口,還可以繼承其它類。
  2. 在這種方式下,多個線程可以共享一個target對象,所以非常適合多個線程來處理同一份資源情況。
  3. 如果需要訪問當前線程,需要使用Thread.currentThread方法。
  4. Callable接口與Runnable接口相比,只是Callable接口可以返回值而已。

用Thread類的方式創建多線程的特點:

  1. 因為線程已經繼承Thread類,所以不可以再繼承其它類。
  2. 如果需要訪問當前線程,直接使用this即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM