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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java并发编程—说说Runnable与Callable

發(fā)布時(shí)間:2024/4/15 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java并发编程—说说Runnable与Callable 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文作者:每天一點(diǎn)

原文地址:說說Runnable與Callable

首先,我們先看看使用Callable創(chuàng)建線程與使用Runable的區(qū)別:

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

首先,實(shí)現(xiàn)Callable而重寫的方法具有返回值,并且擁有泛型,這提高了線程的細(xì)粒度。

實(shí)現(xiàn)Runable接口創(chuàng)建線程方式:

//實(shí)現(xiàn)Runable創(chuàng)建線程的方式 MyThread myThread = new MyThread(); Thread thread = new Thread(myThread);

實(shí)現(xiàn)Callable接口創(chuàng)建線程方式

查閱API我們可以發(fā)現(xiàn),在Thread的構(gòu)造方法中并沒有使用Callable作為參數(shù)的構(gòu)造器。解決辦法:我們先查看Runable接口,

可以發(fā)現(xiàn)有一個(gè)FutureTask的實(shí)現(xiàn)類,點(diǎn)進(jìn)這個(gè)實(shí)現(xiàn)類,我們可以發(fā)現(xiàn)在這個(gè)類的構(gòu)造方法中就可以傳Callable對(duì)象

所以我們可以借助FutureTask這個(gè)類,具體創(chuàng)建代碼如下:

//實(shí)現(xiàn)Callable創(chuàng)建線程的方式 FutureTask futureTask = new FutureTask(new MyThread1()); Thread thread1 = new Thread(futureTask);

這里有個(gè)細(xì)節(jié):如果我們?cè)谑咕€程睡眠5秒鐘,然后使用futureTask.get()方法,會(huì)發(fā)現(xiàn)結(jié)果會(huì)等5秒才出現(xiàn),說明get()方法是有阻塞效果

//實(shí)現(xiàn)Callable class MyThread1 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("進(jìn)入方法中");Thread.sleep(5000);return 1000;} }public class Test {public static void main(String[] args) {//實(shí)現(xiàn)Callable創(chuàng)建線程的方式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();}} }

并且只執(zhí)行了一次,因?yàn)橐粋€(gè)futureTask,不管幾個(gè)線程調(diào)用,調(diào)用的都是同一個(gè)futureTask對(duì)象

Callable接口:

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

Runnable接口:

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

相同點(diǎn):

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

  • 兩者最大的不同點(diǎn)是:實(shí)現(xiàn)Callable接口的任務(wù)線程能返回執(zhí)行結(jié)果;而實(shí)現(xiàn)Runnable接口的任務(wù)線程不能返回結(jié)果;
  • Callable接口的call()方法允許拋出異常;而Runnable接口的run()方法的異常只能在內(nèi)部消化,不能繼續(xù)上拋;
  • 注意點(diǎn):

    • Callable接口支持返回執(zhí)行結(jié)果,此時(shí)需要調(diào)用FutureTask.get()方法實(shí)現(xiàn),此方法會(huì)阻塞主線程直到獲取‘將來’結(jié)果;當(dāng)不調(diào)用此方法時(shí),主線程不會(huì)阻塞!

    寫此篇的原因是一次面試中問到Callable與Runnable的區(qū)別,當(dāng)時(shí)用的多的是Runnable,而Callable使用很少!比較了兩者后(網(wǎng)上查了不少),發(fā)現(xiàn)Callable在很多特殊的場(chǎng)景下還是很有用的!最后留點(diǎn)抄的代碼,加深對(duì)Callable的認(rèn)識(shí)!

    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());}} }

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。