【Java併發編程】——Java創建線程的四種方式,以及創建守護線程

1、繼承Thread類

使用便利,但Java是單繼承,繼承了Thread類就不能繼承其它類了

public class ThreadTest extends Thread{
    public void run() {
        System.out.println(currentThread().getName());
    }

    public static void main(String[] args) {
        ThreadTest thread1 = new ThreadTest();
        ThreadTest thread2 = new ThreadTest();
        thread1.start();
        thread2.start();
    }
}

2、實現Runnable接口

使用接口,避免了單繼承的侷限

public class ThreadTest implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        Thread thread1 = new Thread(threadTest, "線程1");
        Thread thread2 = new Thread(threadTest, "線程2");
        thread1.start();
        thread2.start();
    }

}

3、使用FutureTask方法

以上兩種創建方法都不帶返回值,而用FutureTask方法創建線程,則有返回值

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

public class ThreadTest implements Callable<String> {

    @Override
    public String call() {
        String name = Thread.currentThread().getName();
        return name;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(new ThreadTest());
        Thread thread1 = new Thread(futureTask, "線程1");
        Thread thread2 = new Thread(futureTask, "線程2");
        thread1.start();
        thread2.start();
        System.out.println(futureTask.get());
    }
}

同樣,我們創建了兩個線程,都開始運行,但是最終結果卻只有一個返回值,爲什麼?

那是因爲我們使用FutureTask的時候,只能有一個返回值,如果多個線程同時使用,則後執行的線程的返回值,會覆蓋之前的返回值,所以最終只會有一個返回值 

4、線程池創建線程

 

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static java.lang.Thread.sleep;

public class ThreadTest{

    public static void main(String[] args) {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0 ; i < 3 ; i++) {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cachedThreadPool.execute(() -> System.out.println(Thread.currentThread().getName()));
        }
    }
}

由結果我們可以看到,每次執行都是在同一個線程池中使用同一個線程,因爲這種方法可以不創建新的線程,而是一個線程執行完當前任務後,就可以去執行下一個任務,不必新建

 

(不建議使用Executors去創建,因爲會由於任務過多而導致內存溢出)

建議使用ThreadPooLExecutor的方式去創建線程池

創建守護進程

public class ThreadTest {

    public static void main(String[] args) {
        Thread daemonThread = new Thread(() -> {
            System.out.println("創建一個守護進程");
        });
        // 設置爲守護進程
        daemonThread.setDaemon(true);
        daemonThread.start();
    }
}
  • 如果創建一個用戶線程,那麼即使主線程已經執行完,JVM還要等所有用戶線程也執行完,纔可以退出。
  • 如果創建一個守護線程,那麼主線程執行完之後,JVM不用等守護線程退出,而是直接退出。
ps -eaf|grep java // 查看JVM進程

 如果你希望在主線程結束後JVM進程馬上結束,那麼在創建線程時可以將其設置爲守護線程,如果你希望在主線程結束後子線程繼續工作,等子線程結束後再讓JVM進程結束,那麼就將子線程設置爲用戶線程

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章