日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Java并发编程—说说Runnable与Callable

發布時間:2024/4/15 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java并发编程—说说Runnable与Callable 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文作者:每天一點

原文地址:說說Runnable與Callable

首先,我們先看看使用Callable創建線程與使用Runable的區別:

import java.util.concurrent.Callable;//實現Runable class MyThread implements Runnable {@Overridepublic void run() {} }//實現Callable class MyThread1 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {return null;} }

首先,實現Callable而重寫的方法具有返回值,并且擁有泛型,這提高了線程的細粒度。

實現Runable接口創建線程方式:

//實現Runable創建線程的方式 MyThread myThread = new MyThread(); Thread thread = new Thread(myThread);

實現Callable接口創建線程方式

查閱API我們可以發現,在Thread的構造方法中并沒有使用Callable作為參數的構造器。解決辦法:我們先查看Runable接口,

可以發現有一個FutureTask的實現類,點進這個實現類,我們可以發現在這個類的構造方法中就可以傳Callable對象

所以我們可以借助FutureTask這個類,具體創建代碼如下:

//實現Callable創建線程的方式 FutureTask futureTask = new FutureTask(new MyThread1()); Thread thread1 = new Thread(futureTask);

這里有個細節:如果我們在使線程睡眠5秒鐘,然后使用futureTask.get()方法,會發現結果會等5秒才出現,說明get()方法是有阻塞效果

//實現Callable class MyThread1 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("進入方法中");Thread.sleep(5000);return 1000;} }public class Test {public static void main(String[] args) {//實現Callable創建線程的方式FutureTask futureTask = new FutureTask(new MyThread1());new Thread(futureTask, "AAA").start();try {System.out.println(futureTask.get());System.out.println("main");} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}} }

并且只執行了一次,因為一個futureTask,不管幾個線程調用,調用的都是同一個futureTask對象

Callable接口:

public interface Callable<V> {V call() throws Exception; }

Runnable接口:

public interface Runnable {public abstract void run(); }

相同點:

  • 兩者都是接口;(廢話)
  • 兩者都可用來編寫多線程程序;
  • 兩者都需要調用Thread.start()啟動線程;
  • 不同點:

  • 兩者最大的不同點是:實現Callable接口的任務線程能返回執行結果;而實現Runnable接口的任務線程不能返回結果;
  • Callable接口的call()方法允許拋出異常;而Runnable接口的run()方法的異常只能在內部消化,不能繼續上拋;
  • 注意點:

    • Callable接口支持返回執行結果,此時需要調用FutureTask.get()方法實現,此方法會阻塞主線程直到獲取‘將來’結果;當不調用此方法時,主線程不會阻塞!

    寫此篇的原因是一次面試中問到Callable與Runnable的區別,當時用的多的是Runnable,而Callable使用很少!比較了兩者后(網上查了不少),發現Callable在很多特殊的場景下還是很有用的!最后留點抄的代碼,加深對Callable的認識!

    package com.inte.fork; import java.util.*; import java.util.concurrent.*; import static java.util.Arrays.asList;public class Sums {static class Sum implements Callable<Long> {private final long from;private final long to;Sum(long from, long to) {this.from = from;this.to = to;}@Overridepublic Long call() {long acc = 0;for (long i = from; i <= to; i++) {acc = acc + i;}System.out.println(Thread.currentThread().getName() + " : " + acc);return acc;}}public static void main(String[] args) throws Exception {ExecutorService executor = Executors.newFixedThreadPool(3);List<Future<Long>> results = executor.invokeAll(asList(new Sum(0, 10), new Sum(0, 1_000), new Sum(0, 1_000_000)));executor.shutdown();for (Future<Long> result : results) {System.out.println(result.get());}} }

    總結

    以上是生活随笔為你收集整理的Java并发编程—说说Runnable与Callable的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。