AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁(yè) > 科技  > 軟件

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

來(lái)源: 責(zé)編: 時(shí)間:2023-10-17 09:38:52 305觀看
導(dǎo)讀如果您的應(yīng)用程序與那些能夠同時(shí)處理多個(gè)任務(wù)的應(yīng)用程序相比表現(xiàn)不佳,很可能是因?yàn)樗菃尉€程的。解決這個(gè)問(wèn)題的方法之一是采用多線程技術(shù)。以下是一些可以考慮的方法:線程(Thread)并行流(Parallel Streams)ExecutorServic

如果您的應(yīng)用程序與那些能夠同時(shí)處理多個(gè)任務(wù)的應(yīng)用程序相比表現(xiàn)不佳,很可能是因?yàn)樗菃尉€程的。解決這個(gè)問(wèn)題的方法之一是采用多線程技術(shù)。EQI28資訊網(wǎng)——每日最新資訊28at.com

以下是一些可以考慮的方法:EQI28資訊網(wǎng)——每日最新資訊28at.com

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

適當(dāng)?shù)厥褂眠@些方法,可以徹底改變您的應(yīng)用程序,并推動(dòng)您的職業(yè)發(fā)展。下面我們來(lái)看看如何將您的應(yīng)用程序轉(zhuǎn)變?yōu)楦咝У亩嗑€程應(yīng)用。EQI28資訊網(wǎng)——每日最新資訊28at.com

EQI28資訊網(wǎng)——每日最新資訊28at.com

1. 線程(Thread)

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

CustomTask 每隔50毫秒從0數(shù)到 count - 1。EQI28資訊網(wǎng)——每日最新資訊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 是該類的三個(gè)實(shí)例。EQI28資訊網(wǎng)——每日最新資訊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));

請(qǐng)注意,b 預(yù)計(jì)計(jì)數(shù)的次數(shù)是其他實(shí)例的兩倍。您希望在 a 和 c 順序運(yùn)行的同時(shí)運(yùn)行 b。EQI28資訊網(wǎng)——每日最新資訊28at.com

EQI28資訊網(wǎng)——每日最新資訊28at.com

您可以非常容易地實(shí)現(xiàn)這種行為。EQI28資訊網(wǎng)——每日最新資訊28at.com

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

以下是結(jié)果:EQI28資訊網(wǎng)——每日最新資訊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 同時(shí)開始運(yùn)行,輪流輸出。a 完成后,c 開始執(zhí)行。此外,它們?nèi)吭诓煌木€程中運(yùn)行。通過(guò)手動(dòng)創(chuàng)建 Thread 實(shí)例,您可以完全控制它們。EQI28資訊網(wǎng)——每日最新資訊28at.com

然而,請(qǐng)注意,低級(jí)線程處理也需要同步和資源管理,這可能更容易出錯(cuò)和復(fù)雜。EQI28資訊網(wǎng)——每日最新資訊28at.com

2. 并行流(Parallel Streams)

當(dāng)您需要對(duì)大型集合中的所有元素應(yīng)用相同、重復(fù)且獨(dú)立的任務(wù)時(shí),并行流非常有效。EQI28資訊網(wǎng)——每日最新資訊28at.com

例如,圖像調(diào)整大小是一個(gè)需要按順序運(yùn)行的繁重任務(wù);當(dāng)您有多個(gè)圖像需要調(diào)整大小時(shí),如果按順序執(zhí)行,將需要很長(zhǎng)時(shí)間才能完成。在這種情況下,您可以使用并行流并行調(diào)整它們的大小,如下所示。EQI28資訊網(wǎng)——每日最新資訊28at.com

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

這樣,圖像將同時(shí)調(diào)整大小,節(jié)省了大量寶貴的時(shí)間。EQI28資訊網(wǎng)——每日最新資訊28at.com

3. ExecutorService

當(dāng)實(shí)現(xiàn)不需要精確的線程控制時(shí),可以考慮使用 ExecutorService。ExecutorService 提供了更高層次的線程管理抽象,包括線程池、任務(wù)調(diào)度和資源管理。EQI28資訊網(wǎng)——每日最新資訊28at.com

ExecutorService 是一個(gè)接口,它最常見的用法是線程池。假設(shè)您有大量的異步任務(wù)堆積在一起,但是同時(shí)運(yùn)行所有任務(wù)——每個(gè)任務(wù)占用一個(gè)線程——似乎太多了。線程池可以通過(guò)限制最大線程數(shù)來(lái)幫助您。EQI28資訊網(wǎng)——每日最新資訊28at.com

下面的示例中,我們使用 Executors.newFixedThreadPool() 實(shí)例化 ExecutorService 來(lái)使用 3 個(gè)線程運(yùn)行 10 個(gè)任務(wù)。每個(gè)任務(wù)只打印一行。請(qǐng)注意,我們?cè)谥暗牟糠种兄赜昧酥岸x的 CustomTask。EQI28資訊網(wǎng)——每日最新資訊28at.com

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

這將打印以下結(jié)果:EQI28資訊網(wǎng)——每日最新資訊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 個(gè)任務(wù)在 3 個(gè)線程中運(yùn)行。通過(guò)限制特定任務(wù)使用的線程數(shù),您可以根據(jù)優(yōu)先級(jí)分配線程數(shù):對(duì)于重要且頻繁的任務(wù)使用更多線程,對(duì)于瑣碎或偶爾的任務(wù)使用較少線程。ExecutorService 具有高效和簡(jiǎn)潔的特點(diǎn),是大多數(shù)多線程場(chǎng)景的首選選項(xiàng)。EQI28資訊網(wǎng)——每日最新資訊28at.com

如果您需要更多的控制和靈活性,請(qǐng)查看 ThreadPoolExecutor,它是 Executors.newFixedThreadPool() 返回的 ExecutorService 的實(shí)際實(shí)現(xiàn)。您可以直接創(chuàng)建其實(shí)例或?qū)⒎祷氐?nbsp;ExecutorService 實(shí)例轉(zhuǎn)換為 ThreadPoolExecutor 實(shí)例以獲得更多控制權(quán)。EQI28資訊網(wǎng)——每日最新資訊28at.com

4. ForkJoinPool

ForkJoinPool是另一種線程池,正如其名稱所示。雖然它在許多其他異步方法的底層使用中,但對(duì)于可以分解為較小且獨(dú)立子任務(wù)的任務(wù)來(lái)說(shuō),它也非常強(qiáng)大,這些任務(wù)可以通過(guò)分而治之的策略來(lái)解決。EQI28資訊網(wǎng)——每日最新資訊28at.com

其中一個(gè)任務(wù)是圖像調(diào)整大小。圖像調(diào)整大小是分而治之問(wèn)題的一個(gè)很好的例子。使用ForkJoinPool,您可以將圖像分成兩個(gè)或四個(gè)較小的圖像,并同時(shí)調(diào)整它們的大小。以下是ImageResizeAction的示例,它將圖像調(diào)整為給定的大小。EQI28資訊網(wǎng)——每日最新資訊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);            }        }    }}

請(qǐng)注意,ImageResizeAction繼承了RecursiveAction。RecursiveAction用于定義遞歸的調(diào)整大小操作。在此示例中,圖像被分成兩半并并行調(diào)整大小。EQI28資訊網(wǎng)——每日最新資訊28at.com

您可以使用以下代碼運(yùn)行ImageResizeAction:EQI28資訊網(wǎng)——每日最新資訊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("圖像調(diào)整大小成功!");}

借助ForkJoinPool的幫助,您現(xiàn)在能夠更高效地調(diào)整圖像的大小,具有更好的可伸縮性,并最大程度地利用資源。EQI28資訊網(wǎng)——每日最新資訊28at.com

5. CompletableFuture

通過(guò)CompletableFuture,您可以完全發(fā)揮Future的功能,并擁有許多額外的特性。其中最突出的功能是它能夠鏈?zhǔn)降剡B接異步操作,使您能夠構(gòu)建復(fù)雜的異步管道。EQI28資訊網(wǎng)——每日最新資訊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("結(jié)果:" + data);    });    future.join();}

上述代碼展示了CompletableFuture的一個(gè)關(guān)鍵方面:鏈?zhǔn)讲僮鳌Mㄟ^(guò)CompletableFuture.supplyAsync(),首先創(chuàng)建并運(yùn)行一個(gè)返回字符串結(jié)果的CompletableFuture。thenApply()接受前一個(gè)任務(wù)的結(jié)果,并執(zhí)行其他操作,本例中是添加一個(gè)字符串。最后,thenAccept()打印生成的數(shù)據(jù)。結(jié)果如下所示:EQI28資訊網(wǎng)——每日最新資訊28at.com

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

有3個(gè)任務(wù)沒(méi)有在主線程中運(yùn)行,這表明它們與主邏輯并行運(yùn)行。當(dāng)您有具有結(jié)果并需要鏈接的任務(wù)時(shí),CompletableFuture將是一個(gè)很好的選擇。EQI28資訊網(wǎng)——每日最新資訊28at.com

6. 總結(jié)

多線程是一種強(qiáng)大的工具,可以幫助開發(fā)人員優(yōu)化性能、提升用戶體驗(yàn)、增強(qiáng)并發(fā)處理能力,并充分利用計(jì)算機(jī)的資源。EQI28資訊網(wǎng)——每日最新資訊28at.com

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

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 實(shí)戰(zhàn)!用 Arthas 定位 Spring Boot 接口的超時(shí)問(wèn)題,讓應(yīng)用起飛

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

標(biāo)簽:
  • 熱門焦點(diǎn)
Top