日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

掌握這五種多線程方法,提高Java代碼效率

來源: 責編: 時間:2023-10-17 09:38:52 284觀看
導讀如果您的應用程序與那些能夠同時處理多個任務的應用程序相比表現不佳,很可能是因為它是單線程的。解決這個問題的方法之一是采用多線程技術。以下是一些可以考慮的方法:線程(Thread)并行流(Parallel Streams)ExecutorServic

如果您的應用程序與那些能夠同時處理多個任務的應用程序相比表現不佳,很可能是因為它是單線程的。解決這個問題的方法之一是采用多線程技術。0dG28資訊網——每日最新資訊28at.com

以下是一些可以考慮的方法:0dG28資訊網——每日最新資訊28at.com

  • 線程(Thread)
  • 并行流(Parallel Streams)
  • ExecutorService
  • ForkJoinPool
  • CompletableFuture

適當地使用這些方法,可以徹底改變您的應用程序,并推動您的職業發展。下面我們來看看如何將您的應用程序轉變為高效的多線程應用。0dG28資訊網——每日最新資訊28at.com

0dG28資訊網——每日最新資訊28at.com

1. 線程(Thread)

第一種選擇是使用線程(Thread)類。通過這種方式,您可以直接控制線程的創建和管理。以下是一個示例:0dG28資訊網——每日最新資訊28at.com

CustomTask 每隔50毫秒從0數到 count - 1。0dG28資訊網——每日最新資訊28at.com

public class CustomTask implements Runnable {    private final String name;    private final int count;    CustomTask(String name, int count) {        this.name = name;        this.count = count;    }    @Override    public void run() {        for (int i = 0; i < count; i++) {            System.out.println(name + "-" + i + " from " +                    Thread.currentThread().getName());            try {                Thread.sleep(50);            } catch (InterruptedException e) {                throw new RuntimeException(e);            }        }    }}

a、b 和 c 是該類的三個實例。0dG28資訊網——每日最新資訊28at.com

Thread a = new Thread(new CustomTask("a", 5));Thread b = new Thread(new CustomTask("b", 10));Thread c = new Thread(new CustomTask("c", 5));

請注意,b 預計計數的次數是其他實例的兩倍。您希望在 a 和 c 順序運行的同時運行 b。0dG28資訊網——每日最新資訊28at.com

0dG28資訊網——每日最新資訊28at.com

您可以非常容易地實現這種行為。0dG28資訊網——每日最新資訊28at.com

// 首先啟動 a 和 b。a.start();b.start();//  a 完成后開始 c。a.join();c.start();

以下是結果:0dG28資訊網——每日最新資訊28at.com

a-0 from Thread-0b-0 from Thread-1b-1 from Thread-1a-1 from Thread-0b-2 from Thread-1a-2 from Thread-0b-3 from Thread-1a-3 from Thread-0b-4 from Thread-1a-4 from Thread-0b-5 from Thread-1c-0 from Thread-2b-6 from Thread-1c-1 from Thread-2b-7 from Thread-1c-2 from Thread-2b-8 from Thread-1c-3 from Thread-2b-9 from Thread-1c-4 from Thread-2

a 和 b 同時開始運行,輪流輸出。a 完成后,c 開始執行。此外,它們全部在不同的線程中運行。通過手動創建 Thread 實例,您可以完全控制它們。0dG28資訊網——每日最新資訊28at.com

然而,請注意,低級線程處理也需要同步和資源管理,這可能更容易出錯和復雜。0dG28資訊網——每日最新資訊28at.com

2. 并行流(Parallel Streams)

當您需要對大型集合中的所有元素應用相同、重復且獨立的任務時,并行流非常有效。0dG28資訊網——每日最新資訊28at.com

例如,圖像調整大小是一個需要按順序運行的繁重任務;當您有多個圖像需要調整大小時,如果按順序執行,將需要很長時間才能完成。在這種情況下,您可以使用并行流并行調整它們的大小,如下所示。0dG28資訊網——每日最新資訊28at.com

private static List<BufferedImage> resizeAll(List<BufferedImage> sourceImages,                                             int width, int height) {    return sourceImages            .parallelStream()            .map(source -> resize(source, width, height))            .toList();}

這樣,圖像將同時調整大小,節省了大量寶貴的時間。0dG28資訊網——每日最新資訊28at.com

3. ExecutorService

當實現不需要精確的線程控制時,可以考慮使用 ExecutorService。ExecutorService 提供了更高層次的線程管理抽象,包括線程池、任務調度和資源管理。0dG28資訊網——每日最新資訊28at.com

ExecutorService 是一個接口,它最常見的用法是線程池。假設您有大量的異步任務堆積在一起,但是同時運行所有任務——每個任務占用一個線程——似乎太多了。線程池可以通過限制最大線程數來幫助您。0dG28資訊網——每日最新資訊28at.com

下面的示例中,我們使用 Executors.newFixedThreadPool() 實例化 ExecutorService 來使用 3 個線程運行 10 個任務。每個任務只打印一行。請注意,我們在之前的部分中重用了之前定義的 CustomTask。0dG28資訊網——每日最新資訊28at.com

ExecutorService executorService = Executors.newFixedThreadPool(3);for (int i = 0; i < 10; i++) {    executorService.submit(new CustomTask(String.valueOf(i), 1));}executorService.shutdown();

這將打印以下結果:0dG28資訊網——每日最新資訊28at.com

0-0 from pool-1-thread-12-0 from pool-1-thread-31-0 from pool-1-thread-24-0 from pool-1-thread-33-0 from pool-1-thread-25-0 from pool-1-thread-16-0 from pool-1-thread-17-0 from pool-1-thread-38-0 from pool-1-thread-29-0 from pool-1-thread-3

10 個任務在 3 個線程中運行。通過限制特定任務使用的線程數,您可以根據優先級分配線程數:對于重要且頻繁的任務使用更多線程,對于瑣碎或偶爾的任務使用較少線程。ExecutorService 具有高效和簡潔的特點,是大多數多線程場景的首選選項。0dG28資訊網——每日最新資訊28at.com

如果您需要更多的控制和靈活性,請查看 ThreadPoolExecutor,它是 Executors.newFixedThreadPool() 返回的 ExecutorService 的實際實現。您可以直接創建其實例或將返回的 ExecutorService 實例轉換為 ThreadPoolExecutor 實例以獲得更多控制權。0dG28資訊網——每日最新資訊28at.com

4. ForkJoinPool

ForkJoinPool是另一種線程池,正如其名稱所示。雖然它在許多其他異步方法的底層使用中,但對于可以分解為較小且獨立子任務的任務來說,它也非常強大,這些任務可以通過分而治之的策略來解決。0dG28資訊網——每日最新資訊28at.com

其中一個任務是圖像調整大小。圖像調整大小是分而治之問題的一個很好的例子。使用ForkJoinPool,您可以將圖像分成兩個或四個較小的圖像,并同時調整它們的大小。以下是ImageResizeAction的示例,它將圖像調整為給定的大小。0dG28資訊網——每日最新資訊28at.com

package multithreading;import java.awt.image.BufferedImage;import java.util.concurrent.RecursiveAction;public class ImageResizeAction extends RecursiveAction {    private static final int THRESHOLD = 100;    private final BufferedImage sourceImage;    private final BufferedImage targetImage;    private final int startRow;    private final int endRow;    private final int targetWidth;    private final int targetHeight;    public ImageResizeAction(BufferedImage sourceImage,                             BufferedImage targetImage,                             int startRow, int endRow,                             int targetWidth, int targetHeight) {        this.sourceImage = sourceImage;        this.targetImage = targetImage;        this.startRow = startRow;        this.endRow = endRow;        this.targetWidth = targetWidth;        this.targetHeight = targetHeight;    }    @Override    protected void compute() {        if (endRow - startRow <= THRESHOLD) {            resizeImage();        } else {            int midRow = startRow + (endRow - startRow) / 2;            invokeAll(                    new ImageResizeAction(sourceImage, targetImage,                            startRow, midRow, targetWidth, targetHeight),                    new ImageResizeAction(sourceImage, targetImage,                            midRow, endRow, targetWidth, targetHeight)            );        }    }    private void resizeImage() {        int sourceWidth = sourceImage.getWidth();        double xScale = (double) targetWidth / sourceWidth;        double yScale = (double) targetHeight / sourceImage.getHeight();        for (int y = startRow; y < endRow; y++) {            for (int x = 0; x < sourceWidth; x++) {                int targetX = (int) (x * xScale);                int targetY = (int) (y * yScale);                int rgb = sourceImage.getRGB(x, y);                targetImage.setRGB(targetX, targetY, rgb);            }        }    }}

請注意,ImageResizeAction繼承了RecursiveAction。RecursiveAction用于定義遞歸的調整大小操作。在此示例中,圖像被分成兩半并并行調整大小。0dG28資訊網——每日最新資訊28at.com

您可以使用以下代碼運行ImageResizeAction:0dG28資訊網——每日最新資訊28at.com

public static void main(String[] args) throws IOException {    String sourceImagePath = "source_image.jpg";    String targetImagePath = "target_image.png";    int targetWidth = 300;    int targetHeight = 100;    BufferedImage sourceImage = ImageIO.read(new File(sourceImagePath));    BufferedImage targetImage = new BufferedImage(targetWidth, targetHeight,            BufferedImage.TYPE_INT_RGB);    ForkJoinPool forkJoinPool = new ForkJoinPool();    forkJoinPool.invoke(new ImageResizeAction(sourceImage, targetImage,            0, sourceImage.getHeight(), targetWidth, targetHeight));    ImageIO.write(targetImage, "png", new File(targetImagePath));    System.out.println("圖像調整大小成功!");}

借助ForkJoinPool的幫助,您現在能夠更高效地調整圖像的大小,具有更好的可伸縮性,并最大程度地利用資源。0dG28資訊網——每日最新資訊28at.com

5. CompletableFuture

通過CompletableFuture,您可以完全發揮Future的功能,并擁有許多額外的特性。其中最突出的功能是它能夠鏈式地連接異步操作,使您能夠構建復雜的異步管道。0dG28資訊網——每日最新資訊28at.com

public static void main(String[] args) {    CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {        System.out.println(Thread.currentThread().getName());        return "Hyuni Kim";    }).thenApply((data) -> {        System.out.println(Thread.currentThread().getName());        return "我的名字是" + data;    }).thenAccept((data) -> {        System.out.println(Thread.currentThread().getName());        System.out.println("結果:" + data);    });    future.join();}

上述代碼展示了CompletableFuture的一個關鍵方面:鏈式操作。通過CompletableFuture.supplyAsync(),首先創建并運行一個返回字符串結果的CompletableFuture。thenApply()接受前一個任務的結果,并執行其他操作,本例中是添加一個字符串。最后,thenAccept()打印生成的數據。結果如下所示:0dG28資訊網——每日最新資訊28at.com

ForkJoinPool.commonPool-worker-1ForkJoinPool.commonPool-worker-1ForkJoinPool.commonPool-worker-1Result: My name is Hyuni Kim

有3個任務沒有在主線程中運行,這表明它們與主邏輯并行運行。當您有具有結果并需要鏈接的任務時,CompletableFuture將是一個很好的選擇。0dG28資訊網——每日最新資訊28at.com

6. 總結

多線程是一種強大的工具,可以幫助開發人員優化性能、提升用戶體驗、增強并發處理能力,并充分利用計算機的資源。0dG28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-13639-0.html掌握這五種多線程方法,提高Java代碼效率

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 實戰!用 Arthas 定位 Spring Boot 接口的超時問題,讓應用起飛

下一篇: 8000字+22張圖探秘SpringCloud配置中心的核心原理

標簽:
  • 熱門焦點
  • 小米官宣:2023年上半年出貨量中國第一!

    今日早間,小米電視官方微博帶來消息,稱2023年小米電視上半年出貨量達到了中國第一,同時還表示小米電視的巨屏風暴即將開始。“公布一個好消息2023年#小米電視上半年出貨量中國
  • 6月安卓手機好評榜:魅族20 Pro蟬聯冠軍

    性能榜和性價比榜之后,我們來看最后的安卓手機好評榜,數據來源安兔兔評測,收集時間2023年6月1日至6月30日,僅限國內市場。第一名:魅族20 Pro好評率:95%5月份的時候魅族20 Pro就是
  • 6月安卓手機性價比榜:Note 12 Turbo斷層式碾壓

    6月份有一個618,雖然這是京東周年慶的日子,但別的電商也都不約而同的跟進了,反正促銷沒壞處,廠商和用戶都能滿意。618期間一些產品也出現了歷史低價,那么各個價位段的產品性價比
  • Golang 中的 io 包詳解:組合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是對Reader和Writer接口的組合,
  • 多線程開發帶來的問題與解決方法

    使用多線程主要會帶來以下幾個問題:(一)線程安全問題  線程安全問題指的是在某一線程從開始訪問到結束訪問某一數據期間,該數據被其他的線程所修改,那么對于當前線程而言,該線程
  • 拼多多APP上線本地生活入口,群雄逐鹿萬億市場

    Tech星球(微信ID:tech618)文 | 陳橋輝 Tech星球獨家獲悉,拼多多在其APP內上線了&ldquo;本地生活&rdquo;入口,位置較深,位于首頁的&ldquo;充值中心&rdquo;內,目前主要售賣美食相關的
  • 小米MIX Fold 3配置細節曝光:搭載領先版驍龍8 Gen2+罕見5倍長焦

    這段時間以來,包括三星、一加、榮耀等等有不少品牌旗下的最新折疊屏旗艦都得到了不少爆料,而小米新一代折疊屏旗艦——小米MIX Fold 3此前也屢屢被傳
  • iQOO 11S新品發布會

    iQOO將在7月4日19:00舉行新品發布會,推出杭州亞運會電競賽事官方用機iQOO 11S。
  • OPPO K11樣張首曝:千元機影像“卷”得真不錯!

    一直以來,OPPO K系列機型都保持著較為均衡的產品體驗,歷來都是2K價位的明星機型,去年推出的OPPO K10和OPPO K10 Pro兩款機型憑借各自的出色配置,堪稱有
Top 主站蜘蛛池模板: 滨州市| 嘉荫县| 察哈| 历史| 彭州市| 高邮市| 金秀| 扎兰屯市| 枞阳县| 嵊泗县| 天津市| 屏山县| 林州市| 新竹县| 玉龙| 新邵县| 疏勒县| 贵溪市| 大竹县| 永德县| 鄂伦春自治旗| 徐水县| 鹤壁市| 治县。| 清镇市| 裕民县| 大同县| 长葛市| 台南县| 理塘县| 肃南| 西安市| 兴义市| 炉霍县| 龙里县| 凤冈县| 交城县| 正定县| 荥经县| 定西市| 东源县|