java多线程4:Callable,Future,FutureTask,CompletableFuture

Callable可以理解为一个加强版的Runnable,他可以有返回值,也可以抛出异常。与线程池Executor结合使用,有两种使用方式:

1. Callable + Future

public class CallableDemo implements Callable<String> {
 
    private String name;
     
    public CallableDemo(String name) {
        this.name = name;
    }
 
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        CallableDemo c1 = new CallableDemo("ningyu");
        CallableDemo c2 = new CallableDemo("zhanglu");
        Future<String> future1 = executor.submit(c1);
        Future<String> future2 = executor.submit(c2);
        executor.shutdown();
        System.out.println("--------------程序会阻塞到这里--------------");
        System.out.println(future1.get());
        System.out.println(future2.get());
    }
 
    @Override
    public String call() throws Exception {
        for (int i=0; i<10; i++) {
            System.out.println(name + " is waiting, step is " + i);
            Thread.sleep(1000);
        }
        return name + " has finished, haha";
    }
}

因为future.get()方法返回的是线程的return结果,所以当线程未完成时,该方法会阻塞。

2.Callable + FutureTask


public class CallableDemo implements Callable<String> {

    private String name;
    
    public CallableDemo(String name) {
        this.name = name;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        CallableDemo c1 = new CallableDemo("ningyu");
        CallableDemo c2 = new CallableDemo("zhanglu");
        FutureTask<String> task1 = new FutureTask<String>(c1);
        FutureTask<String> task2 = new FutureTask<String>(c2);
        executor.submit(task1);
        executor.submit(task2);
        executor.shutdown();
        System.out.println("--------------程序会阻塞到这里--------------");
        System.out.println(task1.get());
        System.out.println(task2.get());
    }

    @Override
    public String call() throws Exception {
        for (int i=0; i<10; i++) {
            System.out.println(name + " is waiting, step is " + i);
            Thread.sleep(1000);
        }
        return name + " has finished, haha";
    }
}

其实Callable+Future最终也是以Callable+FutureTask的形式实现的:
在第一种方式中调用了: Future future = executor.submit(task);
那就让我们看看executor.submit(task)的源码吧:


public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);//可以看到源码中其实是在submit(Callable<T> task)内部创建了一个RunnableFuture<T>接口实现类
    execute(ftask);
    return ftask;
}

而FutureTask又是RunnableFuture的实现类,那就再看看newTaskFor(Callable callable)里面干了什么:


protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

两种方式最终是同样实现的。

3.CompletableFuture

上面例子中子线程结果是通过future.get()阻塞得到的,当然也可以通过轮询future.isDone()来实现异步,但是这样会消耗CPU资源,结果还不能及时得到。CompletableFuture提供了设置事件监听回调的方式,解决该问题。

还是上面的例子,LZ不想阻塞当前线程,但是还是想在子线程完成时输出结果,可以这么做:

public class FutureDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        CompletableFuture.supplyAsync(() -> {
            String name = "ningyu";
            for (int i=0; i<10; i++) { 
                System.out.println(name + " is waiting, step is " + i); 
                try { 
                    Thread.sleep(1000); 
                } 
                catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
            } 
            return name + " has finished, haha"; 
        }).whenComplete((v, e) -> {
            System.out.println(v);
        });
         
        System.out.println("I can do others..");
         
        // new Thread().start()起的是User Thread,但是CompletableFuture起的是Daemon Thread,所以LZ加了个死循环保持程序存活
        while (true) {
             
        }
    }
}

下面具体介绍下CompletableFuture提供的方法:


public T get()
public T get(long timeout, TimeUnit unit)
public T getNow(T valueIfAbsent)

前两个方法用法跟Future一样,都会阻塞。后面一个方法会立即返回:如果线程已经完成则返回结果,否则返回valueIfAbsent。


public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

run开头的线程没有返回值,supply开头的线程有返回值。两个方法都可以传入线程池,如果不传默认使用ForkJoinPool.commonPool()系统级公共线程池。


public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)
public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action, Executor executor)
public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor)

如果第一个线程完成后需要另一个线程进行处理,则使用上面这9个方法。包含apply的方法会接收第一个线程的返回值作为输入参数,结果要返回;包含run的则不会接收上个线程的返回值,结果也不返回;包含accept的会接收上一个线程的返回值作为参数,但自己不提供返回值。没有async结尾的方法会沿用上个线程资源,async结尾的会用一个新的线程资源(如果使用的是同一个线程池,即使是async结尾的也有可能拿到同一个线程资源哦)。例子如下:

public class FutureDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("This is " + Thread.currentThread().getName());
            String name = "ningyu";
            for (int i=0; i<10; i++) { 
                System.out.println(name + " is waiting, step is " + i); 
                try { 
                    Thread.sleep(1000); 
                } catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
            } 
            return name + " has finished, haha."; 
        }, pool).thenApplyAsync(v -> {
            System.out.println("That is " + Thread.currentThread().getName());
            return v + " But he must do another now.";
        });

        System.out.println("I can do others..");

        while (true) {
            
        }
    }
}

输出结果:

public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor)

整合两个子线程的结果调用上面的方法。例子如下:

public class FutureDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {        
        CompletableFuture.supplyAsync(() -> {
            for (int i=0; i<5; i++) { 
                System.out.println("first job step" + i); 
                try { 
                    Thread.sleep(1000); 
                } catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
            } return "first result"; 
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            for (int i=0; i<3; i++) { 
                System.out.println("second job step" + i); 
                try { 
                    Thread.sleep(1000); 
                } catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
            } 
            return "second result"; 
        }), (r1, r2) -> r1 + " and " + r2).thenAccept(r -> System.out.println(r));
        
        while (true) {
            
        }
    }
}

输出结果:

可以看出,整合的两个子线程其实是同步执行的。

public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)

当future完成或者抛出异常的时候回调用上面的方法。

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)

allOf是等待所有任务完成,构造后CompletableFuture完成
anyOf是只要有一个任务完成,构造后CompletableFuture就完成

public class FutureDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        CompletableFuture<String> first = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "first result";
        });
        CompletableFuture<String> second = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "second result";
        });
        
        CompletableFuture.anyOf(new CompletableFuture[] {first, second}).whenComplete((v, e) -> {
            System.out.println(v);
        });
        
        CompletableFuture.allOf(new CompletableFuture[] {first, second});
        
        while (true) {
            
        }
    }
}

anyOf会输出second result,allOf在两个子线程完成之后才会被调用。

261 Replies to “java多线程4:Callable,Future,FutureTask,CompletableFuture”

  1. Pingback: buy cialis pharmatize
  2. Pingback: viagra generic
  3. Pingback: buy cialis in canada
  4. Pingback: ed pills that work
  5. Pingback: men viagra pills
  6. Pingback: 80mg cialis
  7. Pingback: sinkaltim
  8. Pingback: classfaqs
  9. Pingback: do-posle-psihologa
  10. Pingback: vedspace
  11. Pingback: namasedu
  12. Pingback: technotizie
  13. Pingback: piarnet
  14. Pingback: filpchat
  15. Pingback: luxpetco
  16. Pingback: vulpinoid
  17. Pingback: DPTPtNqS
  18. Pingback: qQ8KZZE6
  19. Pingback: D6tuzANh
  20. Pingback: chinemile
  21. Pingback: SHKALA TONOV
  22. Pingback: bez-diploma
  23. Pingback: 匿名
  24. Pingback: russianmanagement.com
  25. Pingback: chelovek-iz-90-h
  26. Pingback: proevalua
  27. Pingback: torgius
  28. Pingback: 3Hk12Bl
  29. Pingback: 3NOZC44
  30. Pingback: 01211
  31. Pingback: lemmacres
  32. Pingback: morisonsws
  33. Pingback: tor-lyubov-i-grom
  34. Pingback: film-tor-2022
  35. Pingback: hd-tor-2022
  36. Pingback: hdorg2.ru
  37. Pingback: Psikholog
  38. Pingback: lesmatons
  39. Pingback: ericonidi
  40. Pingback: riscad
  41. Pingback: netstate.ru
  42. Pingback: themrsc
  43. Pingback: eseaship
  44. Pingback: blogduwem
  45. Pingback: biasansor
  46. Pingback: catfishmoe
  47. Pingback: Link
  48. Pingback: sellergyllc
  49. Pingback: projoust
  50. Pingback: wearehobo
  51. Pingback: tor-lyubov-i-grom.ru
  52. Pingback: nnz-home
  53. Pingback: caralarma
  54. Pingback: autodynamik
  55. Pingback: webdooni
  56. Pingback: bit.ly
  57. Pingback: cleantalkorg2.ru
  58. Pingback: mygohotels
  59. Pingback: bucha killings
  60. Pingback: War in Ukraine
  61. Pingback: Ukraine
  62. Pingback: Ukraine-Russia
  63. Pingback: cagdasck
  64. Pingback: mj-des
  65. Pingback: site
  66. Pingback: smileytips
  67. Pingback: lesnaudines
  68. Pingback: stats
  69. Pingback: Ukraine-war
  70. Pingback: movies
  71. Pingback: gidonline
  72. Pingback: ambzsalon
  73. Pingback: web
  74. Pingback: film.8filmov.ru
  75. Pingback: video
  76. Pingback: milumba
  77. Pingback: film
  78. Pingback: basewebtek
  79. Pingback: oraien
  80. Pingback: fracingsand
  81. Pingback: progoodies
  82. Pingback: sY5am
  83. Pingback: federalspare
  84. Pingback: westwoodcpr
  85. Pingback: veskopetrov
  86. Pingback: tenergys
  87. Pingback: novynha
  88. Pingback: Dom drakona
  89. Pingback: JGXldbkj
  90. Pingback: aOuSjapt
  91. Pingback: choosegunsafe
  92. Pingback: psikholog moskva
  93. Pingback: Usik Dzhoshua 2 2022
  94. Pingback: thefunnyjunk
  95. Pingback: lausafaaog
  96. Pingback: Dim Drakona 2022
  97. Pingback: ntrfanz
  98. Pingback: TwnE4zl6
  99. Pingback: daphucco
  100. Pingback: psy 3CtwvjS
  101. Pingback: displaysofjamaica
  102. Pingback: hyperkast
  103. Pingback: homembt
  104. Pingback: gtrelarm
  105. Pingback: berhaninjection
  106. Pingback: tquariusmusicusa
  107. Pingback: skytopsneakers
  108. Pingback: vintagebitches
  109. Pingback: lalochesia
  110. Pingback: salnunz
  111. Pingback: blturnerintl
  112. Pingback: shemcreekevents
  113. Pingback: harbourcityhotel
  114. Pingback: vmgear
  115. Pingback: yurtsohbet
  116. Pingback: norgran
  117. Pingback: lvdbulb
  118. Pingback: securetrck
  119. Pingback: film onlinee
  120. Pingback: umseek
  121. Pingback: canseidesercool
  122. Pingback: suviedu
  123. Pingback: riptidesurfbar
  124. Pingback: websinfohk
  125. Pingback: psycholog-v-moskve.ru
  126. Pingback: psycholog-moskva.ru
  127. Pingback: cialisgrn
  128. Pingback: mrwhiterabbit
  129. Pingback: numbmom
  130. Pingback: imwrks
  131. Pingback: 3qAIwwN
  132. Pingback: lebsocial
  133. Pingback: sharlyyou
  134. Pingback: video-2
  135. Pingback: saglikara
  136. Pingback: aselresorthotel
  137. Pingback: sezons.store
  138. Pingback: selivia
  139. Pingback: psy-news.ru
  140. Pingback: raspberrypihacks
  141. Pingback: spretech
  142. Pingback: virukshamtrust
  143. Pingback: rightcoastranch
  144. Pingback: 000-1
  145. Pingback: 3SoTS32
  146. Pingback: 3DGofO7
  147. Pingback: everydaycuvee
  148. Pingback: cissemosse
  149. Pingback: npbusher
  150. Pingback: ukcopiersonline
  151. Pingback: maidsquadtx
  152. Pingback: filecodi
  153. Pingback: sitestats01
  154. Pingback: 1c789.ru
  155. Pingback: cttdu.ru
  156. Pingback: profprsites
  157. Pingback: mcevillage
  158. Pingback: trientry
  159. Pingback: 1703
  160. Pingback: hdserial2023.ru
  161. Pingback: serialhd2023.ru
  162. Pingback: matchonline2022.ru
  163. Pingback: dokanmela
  164. Pingback: forexwale
  165. Pingback: bit.ly/3OEzOZR
  166. Pingback: bit.ly/3gGFqGq
  167. Pingback: detikxom
  168. Pingback: bit.ly/3ARFdXA
  169. Pingback: bit.ly/3ig2UT5
  170. Pingback: bit.ly/3GQNK0J
  171. Pingback: bep5w0Df
  172. Pingback: www
  173. Pingback: icf
  174. Pingback: 24hours-news
  175. Pingback: rusnewsweek
  176. Pingback: uluro-ado
  177. Pingback: irannews.ru
  178. Pingback: klondayk2022
  179. Pingback: avplanner
  180. Pingback: elementsofmsy
  181. Pingback: kuenstlerkolonie
  182. Pingback: goldenpaisa
  183. Pingback: postaim
  184. Pingback: cagataycatal
  185. Pingback: evecalls
  186. Pingback: pelvicworld
  187. Pingback: amosdarnell
  188. Pingback: gaianation
  189. Pingback: communityzap
  190. Pingback: mycoolparty
  191. Pingback: probabilite
  192. Pingback: ahealthynewu
  193. Pingback: miraclefarms
  194. Pingback: dudukner
  195. Pingback: theassetedge
  196. Pingback: susankhya
  197. Pingback: ariumhamptonlake
  198. Pingback: mangalib
  199. Pingback: transmn
  200. Pingback: highgearelectric
  201. Pingback: directchampagnes
  202. Pingback: resiliens
  203. Pingback: jmppromotionsinc
  204. Pingback: karunasoap
  205. Pingback: smukkebryster
  206. Pingback: fifaleague
  207. Pingback: balazskoren
  208. Pingback: stevedekay
  209. Pingback: talazin
  210. Pingback: andylampert
  211. Pingback: execedits
  212. Pingback: celebum
  213. Pingback: cellustra
  214. Pingback: caltav
  215. Pingback: x
  216. Pingback: 9xflix
  217. Pingback: xnxx
  218. Pingback: dizienleri
  219. Pingback: 123movies
  220. Pingback: belpages
  221. Pingback: osterwoche
  222. Pingback: fismare
  223. Pingback: celindamuza
  224. Pingback: video.vipspark.ru
  225. Pingback: vitaliy-abdulov.ru
  226. Pingback: psychophysics.ru
  227. Pingback: vipspark.vipspark.ru
  228. Pingback: sacreddread
  229. Pingback: vpdf
  230. Pingback: transorgs
  231. Pingback: makersfinds
  232. Pingback: filigrania
  233. Pingback: vicksfabs
  234. Pingback: fletsaccess
  235. Pingback: mirkurortov
  236. Pingback: ecvine
  237. Pingback: mseteit
  238. Pingback: lacarspotting
  239. Pingback: besafeab
  240. Pingback: binsarhiras
  241. Pingback: wanakahomes
  242. Pingback: workschon
  243. Pingback: malabarcet
  244. Pingback: rigwares
  245. Pingback: sapporovn
  246. Pingback: taedits
  247. Pingback: cpsmath
  248. Pingback: zinitgroup
  249. Pingback: snapitf

发表评论