最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程中的Callable和Future詳解

 更新時間:2023年08月26日 09:59:07   作者:weixin_34274029  
這篇文章主要介紹了Java多線程中的Callable和Future詳解,創(chuàng)建線程的兩種方式,一種是直接繼承Thread,另外一種就是實現(xiàn)Runnable接口,本文提供了部分代碼,需要的朋友可以參考下

前言

創(chuàng)建線程的兩種方式,一種是直接繼承Thread,另外一種就是實現(xiàn)Runnable接口。

這兩種方式都有一個缺陷就是:在執(zhí)行完任務(wù)之后無法獲取執(zhí)行結(jié)果。

如果需要獲取執(zhí)行結(jié)果,就必須通過共享變量或者使用線程通信的方式來達到效果,這樣使用起來就比較麻煩。

而自從Java 1.5開始,就提供了Callable和Future,通過它們可以在任務(wù)執(zhí)行完畢之后得到任務(wù)執(zhí)行結(jié)果。

一、Runnable接口

先看一下java.lang.Runnable吧,它是一個接口,在它里面只聲明了一個run()方法:

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

由于run()方法返回值為void類型,所以在執(zhí)行完任務(wù)之后無法返回任何結(jié)果。

二、Callable接口

Callable接口位于java.util.concurrent包下,在它里面也只聲明了一個方法,只不過這個方法叫做call()。

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

可以看到,這是一個泛型接口,call()函數(shù)返回的類型就是傳遞進來的V類型。

Callable接口可以看作是Runnable接口的補充,call方法帶有返回值,并且可以拋出異常。

三、FutureTask類

如何獲取Callable的返回結(jié)果呢?一般是通過FutureTask這個中間媒介來實現(xiàn)的。

整體的流程是這樣的:把Callable實例當作參數(shù),生成一個FutureTask的對象,然后把這個對象當作一個Runnable,作為參數(shù)另起線程。

3.1 FutureTask的結(jié)構(gòu)

lingpaitong.png

3.2 FutureTask的啟動

由于FutureTask實現(xiàn)了Runnable,因此它既可以通過Thread包裝來直接執(zhí)行,也可以提交給ExecuteService來執(zhí)行。

下面以Thread包裝線程方式啟動來說明一下。

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class Demo {
    public static void main(String[] args) throws Exception {
        Callable<Integer> call = new Callable<Integer>() {
            public Integer call() throws Exception {
            System.out.println("計算線程正在計算結(jié)果...");
            Thread.sleep(3000);
            return 1;
        }
    };
    FutureTask<Integer> task = new FutureTask<>(call);
    Thread thread = new Thread(task);
    thread.start();
    System.out.println("main線程干點別的...");
    Integer result = task.get();
    System.out.println("從計算線程拿到的結(jié)果為:" + result);
    }
}

四、Future接口

FutureTask繼承體系中的核心接口是Future。

Future的核心思想是:一個方法,計算過程可能非常耗時,等待方法返回,顯然不明智??梢栽谡{(diào)用方法的時候,立馬返回一個Future,可以通過Future這個數(shù)據(jù)結(jié)構(gòu)去控制方法f的計算過程。

這里的控制包括:

  • get方法:獲取計算結(jié)果(如果還沒計算完,也是必須等待的)
  • cancel方法:還沒計算完,可以取消計算過程
  • isDone方法:判斷是否計算完
  • isCancelled方法:判斷計算是否被取消

補充:同樣是獲取線程的計算結(jié)果,Java則顯得很繁瑣,而C語言的實現(xiàn)則簡單的多。

看下面的例子

假設(shè)有兩個函數(shù):

void * dose_do(void * a) {
    for (int i = 0; i < 5; i++) {
        sleep(1);
             puts("does_do");
           }
        return NULL;
        }
void * dose_not(void * a) {
    for (int i = 0; i < 5; i++) {
        sleep(1);
        puts("does_not");
    }
    return NULL;
}

這兩個函數(shù)都返回了void指針,因為void指針可以指向存儲器中任何數(shù)據(jù)類型的數(shù)據(jù),線程函數(shù)的返回類必須是void *。

1、創(chuàng)建線程

創(chuàng)建線程可以使用多種線程庫,在此我們使用最流行的一種:POSIX線程庫,也叫pthread。

必須包含#include <pthread.h>頭文件。

我們使用pthread_create() 函數(shù)創(chuàng)建并運行一個線程,而且每個線程都需要把線程信息保存在一個pthread_t類型的數(shù)據(jù)中。

// 線程對象
pthread_t t0;
pthread_t t1;
if (pthread_create(&t0, NULL, dose_not, NULL) == -1) {
error("無法創(chuàng)建線程t0");
}
if (pthread_create(&t1, NULL, dose_do, NULL) == -1) {
error("無法創(chuàng)建線程t1");
}

2、獲取線程返回值

上邊的兩個函數(shù)將會獨立的在線程中運行直到結(jié)束,但是我們需要知道這兩個函數(shù)什么時候結(jié)束??梢允褂胮thread_join()函數(shù)等待函數(shù)結(jié)束,它會接受線程函數(shù)的返回值,并保存在一個void *類型的數(shù)據(jù)中。那么這個函數(shù)是如何得知線程結(jié)束的呢?當?shù)玫骄€程函數(shù)的返回值的時候,就表明線程函數(shù)結(jié)束了。這也是為什么線程函數(shù)必須要有返回值的原因。

void *result;
if (pthread_join(t0, &result) == -1) {
error("無法回收線程t0");
}
if (pthread_join(t1, &result) == -1) {
error("無法回收線程t1");
}

我們來看全部代碼:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
// 錯誤處理函數(shù)
void error(char *msg) {
    fprintf(stderr, "Error: %s %s", msg, strerror(errno));
    exit(1);
}
void * dose_not(void * a) {
    for (int i = 0; i < 5; i++) {
    sleep(1);
    puts("does_not");
}
return NULL;
}
void * dose_do(void * a) {
    for (int i = 0; i < 5; i++) {
    sleep(1);
    puts("does_do");
}
return NULL;
}
int main(int argc, const char * argv[]) {
// 線程對象
pthread_t t0;
pthread_t t1;
if (pthread_create(&t0, NULL, dose_not, NULL) == -1) {
    error("無法創(chuàng)建線程t0");
}
if (pthread_create(&t1, NULL, dose_do, NULL) == -1) {
    error("無法創(chuàng)建線程t1");
}
void *result;
    if (pthread_join(t0, &result) == -1) {
     error("無法回收線程t0");
}   
    if (pthread_join(t1, &result) == -1) {
     error("無法回收線程t1");
}
return 0;
}

到此這篇關(guān)于Java多線程中的Callable和Future詳解的文章就介紹到這了,更多相關(guān)Java多線程Callable和Future內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決mybatis中order by排序無效問題

    解決mybatis中order by排序無效問題

    這篇文章主要介紹了解決mybatis中order by排序無效問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 如何實現(xiàn)Spring?Event(異步事件)

    如何實現(xiàn)Spring?Event(異步事件)

    這篇文章主要介紹了如何實現(xiàn)Spring?Event(異步事件)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • java高級用法之綁定CPU的線程Thread?Affinity簡介

    java高級用法之綁定CPU的線程Thread?Affinity簡介

    java線程thread affinity是用來將java代碼中的線程綁定到CPU特定的核上,用來提升程序運行的性能,這篇文章主要介紹了java高級用法之綁定CPU的線程thread affinity的相關(guān)知識,需要的朋友可以參考下
    2022-05-05
  • Java自定義Enum的實現(xiàn)示例

    Java自定義Enum的實現(xiàn)示例

    Java中的自定義Enum類型是一種特殊的類,用于表示固定數(shù)量的常量值,本文主要介紹了Java自定義Enum的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • SpringBoot中重要注解詳解

    SpringBoot中重要注解詳解

    文章介紹了Spring?Boot的自動配置機制和一些常用的注解,這些注解用于標識和配置Spring?Boot應(yīng)用中的控制器、路由、響應(yīng)體等組件,本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • SpringBoot限制接口訪問頻率功能實現(xiàn)

    SpringBoot限制接口訪問頻率功能實現(xiàn)

    最近在基于SpringBoot做一個面向普通用戶的系統(tǒng),為了保證系統(tǒng)的穩(wěn)定性,防止被惡意攻擊,我想控制用戶訪問每個接口的頻率,接下來通過本文給大家介紹SpringBoot限制接口訪問頻率功能實現(xiàn),需要的朋友可以參考下
    2023-05-05
  • Idea中SpringBoot多模塊項目的建立實現(xiàn)

    Idea中SpringBoot多模塊項目的建立實現(xiàn)

    這篇文章主要介紹了Idea中SpringBoot多模塊項目的建立實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Spring Boot發(fā)送郵件詳解

    Spring Boot發(fā)送郵件詳解

    這篇文章主要為大家詳細介紹了Spring Boot發(fā)送郵件的相關(guān)資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 基于SpringBoot?Mock單元測試詳解

    基于SpringBoot?Mock單元測試詳解

    這篇文章主要介紹了基于SpringBoot?Mock單元測試詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • MyBatis配置文件中最常用的設(shè)置

    MyBatis配置文件中最常用的設(shè)置

    文章主要介紹了MyBatis配置的優(yōu)化方法,包括引用外部的properties配置文件、配置外置以實現(xiàn)環(huán)境解耦、配置文件中最常用的6個核心設(shè)置以及三種常用的Mapper注冊方式,感興趣的朋友跟隨小編一起看看吧
    2025-12-12

最新評論

梨树县| 鹿泉市| 五莲县| 拜泉县| 土默特左旗| 克拉玛依市| 诏安县| 莎车县| 马关县| 兖州市| 青阳县| 久治县| 宁津县| 奇台县| 阳信县| 楚雄市| 五原县| 新宁县| 枣强县| 枝江市| 泽库县| 定陶县| 辉县市| 从江县| 永济市| 高淳县| 黑河市| 翁牛特旗| 周宁县| 兴山县| 龙州县| 丹凤县| 昭觉县| 布拖县| 延川县| 资兴市| 保康县| 五河县| 东丰县| 从江县| 晋江市|