首頁 > Java > java教程 > 如何在Java中創建並運行執行緒?

如何在Java中創建並運行執行緒?

王林
發布: 2023-04-19 14:16:05
轉載
1607 人瀏覽過

    一、建立並執行執行緒的五種方法

    第一種:繼承Thread類別

    這種方式是最基礎的一種方式,學過java的朋友都知道,不做贅述。要注意的是:覆蓋實作使用的是run方法,運行執行緒是start方法。

    public class FirstWay extends Thread  {
        @Override
        public void run() {
            System.out.println("第一种实现线程的方式:继承Thread类");
        }
        //模拟测试
        public static void main(String[] args) {
            new FirstWay().start();
        }
    }
    登入後複製

    第二種:實作Runnable介面

    第二種實作方式仍然很基礎,繼承Runnable接口,重寫run方法實作執行緒執行邏輯。需要注意的:執行執行緒需要套一層new Thread 。

    public class SecondWay implements Runnable{
        @Override
        public void run() {
            System.out.println("第二种实现线程的方式:实现Runnable接口");
        }
        //模拟测试
        public static void main(String[] args) {
            new Thread(new SecondWay()).start();
        }
    }
    登入後複製

    第三種:實作Callable介面

    第三種方式是實作Callable接口,Callable介面與Runable介面都能實作執行緒。

    public class ThirdWay implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println("第三种实现线程的方式:实现Callable接口");
            return "Callable接口带返回值,可以抛出异常";
        }
    
        //模拟测试
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            FutureTask<String> futureTask = new FutureTask<>(new ThirdWay());
            new Thread(futureTask).start();
            //阻塞方法,获取call方法返回值
            System.out.println(futureTask.get());  //打印:Callable接口带返回值,可以抛出异常
        }
    }
    登入後複製

    差異如下:

    • Callable介面實作執行緒方法是call, Runable介面實作執行緒方法是run

    • Callable有回傳值, Runable介面不能有回傳值

    • Callable介面方法call回傳值可以設定泛型,如下例中使用String資料型別

    • Callable介面方法call方法可以拋出例外,Runable介面run方法不可以拋出例外

    • Callable介面方法透過new Thread(futureTask ).start()運行,FutureTask的get方法可以取得Callable介面方法call方法的回傳值

    • 如果Callable介面方法call方法異常,在FutureTask的get方法調用時也會拋出同樣的異常

    第四種:線程池execute

    從JDK5版本開始,java預設提供了線程池的支持,用線程池的方式運行線程可以避免線程的無限擴張導致應用宕機,同時也節省了線程頻繁創建與銷毀的資源與時間成本。

    public class FourthWay implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() +
                    ":实现线程的方式Runnable接口,但运行方式不一样,使用线程池");
        }
    
        public static void main(String[] args) {
            //创建一个固定大小的线程池
            ExecutorService threadPool = Executors.newFixedThreadPool(5);
            for(int i = 0;i < 10;i++){
                threadPool.execute(new FourthWay());
            }
        }
    }
    登入後複製

    執行緒池ExecutorService使用execute方法執行Runnable介面run方法的執行緒實現,execute方法與run方法的共同特徵是沒有回傳值。

    pool-1-thread-5:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-2:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-4:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-4:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-4:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-1:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-4:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-3:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-2:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-5:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    登入後複製

    從上面的結果可以看出,在執行緒池中包含五個執行緒。執行緒運行完成之後並不銷毀,而是回到執行緒池,下次執行時從執行緒池中取得執行緒資源再次運行。

    第五種:執行緒池submit

    下面的範例執行緒池ExecutorService使用submit方法運行Callable介面call方法的執行緒實現,submit方法與call方法的共同特徵是存在返回值。

    • Callable介面call方法的回傳值可以由泛型定義

    • ExecutorService執行緒池submit方法的傳回值是Future

    Future的get方法可以取得call方法的回傳值,同時如果call方法拋出例外,Future的get方法也會拋出例外。

    public class FifthWay implements Callable<String> {
        @Override
        public String call() throws Exception {
            return Thread.currentThread().getName() + ":Callable接口带返回值,可以抛出异常";
        }
    
        //模拟测试
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //保存多线程执行结果
            List<String> retList = new ArrayList<>();
            //创建一个固定大小的线程池
            ExecutorService threadPool = Executors.newFixedThreadPool(5);
            for(int i = 0;i < 10;i++){
                Future<String> future = threadPool.submit(new FifthWay());
                retList.add(future.get());
            }
            //java8 语法,打印retlist
            retList.forEach(System.out::println);
        }
    }
    登入後複製

    上文程式碼中有一個小小的語法糖,retList.forEach(System.out::println);是java8提供的方法參考

    pool-1-thread-1:Callable接口带返回值,可以抛出异常
    pool-1-thread-2:Callable接口带返回值,可以抛出异常
    pool-1-thread-3:Callable接口带返回值,可以抛出异常
    pool-1-thread-4:Callable接口带返回值,可以抛出异常
    pool-1-thread-5:Callable接口带返回值,可以抛出异常
    pool-1-thread-1:Callable接口带返回值,可以抛出异常
    pool-1-thread-2:Callable接口带返回值,可以抛出异常
    pool-1-thread-3:Callable接口带返回值,可以抛出异常
    pool-1-thread-4:Callable接口带返回值,可以抛出异常
    pool-1-thread-5:Callable接口带返回值,可以抛出异常
    登入後複製

    以上是如何在Java中創建並運行執行緒?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    相關標籤:
    來源:yisu.com
    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
    熱門教學
    更多>
    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板