成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java? 教程(執(zhí)行器)

馬忠志 / 1357人閱讀

執(zhí)行器

在前面的所有示例中,由新的線程(由其Runnable對象定義)和線程本身(由Thread對象定義)完成的任務(wù)之間存在緊密的聯(lián)系,這適用于小型應(yīng)用程序,但在大型應(yīng)用程序中,將線程管理和創(chuàng)建與應(yīng)用程序的其余部分分開是有意義的,封裝這些函數(shù)的對象稱為執(zhí)行器,以下小節(jié)詳細(xì)描述了執(zhí)行器。

執(zhí)行器接口定義三個執(zhí)行器對象類型。

線程池是最常見的執(zhí)行器實(shí)現(xiàn)類型。

Fork/Join是一個利用多個處理器的框架(JDK 7中的新增功能)。

執(zhí)行器接口

java.util.concurrent包定義了三個執(zhí)行器接口:

Executor,一個支持啟動新任務(wù)的簡單接口。

ExecutorService,Executor的子接口,它添加了有助于管理生命周期的功能,包括單個任務(wù)和執(zhí)行器本身。

ScheduledExecutorService,ExecutorService的子接口,支持將來和/或定期執(zhí)行任務(wù)。

通常,引用執(zhí)行器對象的變量被聲明為這三種接口類型之一,而不是執(zhí)行器類類型。

Executor接口

Executor接口提供單個方法execute,旨在成為常見線程創(chuàng)建語法的替代方法,如果rRunnable對象,并且eExecutor對象,則可以替換

(new Thread(r)).start();

e.execute(r);

但是,execute的定義不太具體,低級別語法創(chuàng)建一個新線程并立即啟動它,根據(jù)Executor實(shí)現(xiàn),execute可能會做同樣的事情,但更有可能使用現(xiàn)有的工作線程來運(yùn)行r,或者將r放在隊(duì)列中以等待工作線程變?yōu)榭捎茫ㄎ覀儗⒃诰€程池的部分中描述工作線程)。

java.util.concurrent中的執(zhí)行器實(shí)現(xiàn)旨在充分利用更高級的ExecutorServiceScheduledExecutorService接口,盡管它們也可以與基本Executor接口一起使用。

ExecutorService接口

ExecutorService接口使用類似但更通用的submit方法補(bǔ)充execute,與execute一樣,submit接受Runnable對象,但也接受Callable對象,這允許任務(wù)返回一個值。submit方法返回一個Future對象,該對象用于檢索Callable返回值并管理CallableRunnable任務(wù)的狀態(tài)。

ExecutorService還提供了提交大量Callable對象的方法,最后,ExecutorService提供了許多用于管理執(zhí)行器關(guān)閉的方法,為了支持立即關(guān)閉,任務(wù)應(yīng)該正確處理中斷。

ScheduledExecutorService接口

ScheduledExecutorService接口使用schedule補(bǔ)充其父級ExecutorService的方法,在指定的延遲后執(zhí)行RunnableCallable任務(wù),此外,接口定義了scheduleAtFixedRatescheduleWithFixedDelay,它們以定義的間隔重復(fù)執(zhí)行指定的任務(wù)。

線程池

java.util.concurrent中的大多數(shù)執(zhí)行器實(shí)現(xiàn)都使用由工作線程組成的線程池,這種線程與它執(zhí)行的RunnableCallable任務(wù)分開存在,通常用于執(zhí)行多個任務(wù)。

使用工作線程可以最小化由于創(chuàng)建線程而帶來的開銷,線程對象使用大量內(nèi)存,在大型應(yīng)用程序中,分配和釋放許多線程對象會產(chǎn)生大量的內(nèi)存管理開銷。

一種常見類型的線程池是固定線程池,這種類型的池始終具有指定數(shù)量的線程,如果一個線程在它仍在使用時以某種方式被終止,它將自動被一個新線程替換,任務(wù)通過內(nèi)部隊(duì)列提交到池中,當(dāng)活動任務(wù)多于線程時,該隊(duì)列將保存額外的任務(wù)。

固定線程池的一個重要優(yōu)點(diǎn)是使用它的應(yīng)用程序可以優(yōu)雅地降級,要理解這一點(diǎn),請考慮一個Web服務(wù)器應(yīng)用程序,其中每個HTTP請求都由一個多帶帶的線程處理。如果應(yīng)用程序只是為每個新的HTTP請求創(chuàng)建一個新線程,并且系統(tǒng)接收的請求數(shù)量超過了可以立即處理的數(shù)量,當(dāng)所有這些線程的開銷超過系統(tǒng)容量時,應(yīng)用程序?qū)⑼蝗煌V鬼憫?yīng)所有請求。由于可以創(chuàng)建的線程數(shù)量有限制,應(yīng)用程序不會像HTTP請求進(jìn)入時那樣快地為它們提供服務(wù),而是以系統(tǒng)能夠承受的最快速度為它們提供服務(wù)。

創(chuàng)建使用固定線程池的執(zhí)行器的一種簡單方法是在java.util.concurrent.Executors中調(diào)用newFixedThreadPool工廠方法,該類還提供以下工廠方法:

newCachedThreadPool方法使用可擴(kuò)展線程池創(chuàng)建執(zhí)行器,此執(zhí)行器適用于啟動許多短期任務(wù)的應(yīng)用程序。

newSingleThreadExecutor方法創(chuàng)建一次執(zhí)行單個任務(wù)的執(zhí)行器。

有幾個工廠方法是上述執(zhí)行器的ScheduledExecutorService版本。

如果上述工廠方法提供的執(zhí)行器均無法滿足你的需求,構(gòu)造java.util.concurrent.ThreadPoolExecutor或java.util.concurrent.ScheduledThreadPoolExecutor的實(shí)例將為你提供額外選項(xiàng)。

Fork/Join

fork/join框架是ExecutorService接口的一個實(shí)現(xiàn),可幫助你利用多個處理器,它專為可以遞歸分解成小塊的工作而設(shè)計,目標(biāo)是使用所有可用的處理能力來增強(qiáng)應(yīng)用程序的性能。

與任何ExecutorService實(shí)現(xiàn)一樣,fork/join框架將任務(wù)分配給線程池中的工作線程,fork/join框架是不同的,因?yàn)樗褂昧斯ぷ鞲`取算法,沒有事情可做的工作線程可以從仍然忙碌的其他線程中竊取任務(wù)。

fork/join框架的中心是ForkJoinPool類,它是AbstractExecutorService類的擴(kuò)展,ForkJoinPool實(shí)現(xiàn)了核心工作竊取算法,可以執(zhí)行ForkJoinTask進(jìn)程。

基礎(chǔ)用法

使用fork/join框架的第一步是編寫執(zhí)行工作片段的代碼,你的代碼應(yīng)類似于以下偽代碼:

if (我的工作部分足夠小)
  直接做這項(xiàng)工作
else
  把我的工作分成兩塊
  調(diào)用這兩塊并等待結(jié)果

將此代碼包裝在ForkJoinTask子類中,通常使用其更專業(yè)的類型之一,RecursiveTask(可以返回結(jié)果)或RecursiveAction。

ForkJoinTask子類準(zhǔn)備就緒后,創(chuàng)建表示要完成的所有工作的對象,并將其傳遞給ForkJoinPool實(shí)例的invoke()方法。

模糊清晰度

為了幫助你了解fork/join框架的工作原理,請考慮以下示例,假設(shè)你想模糊圖像,原始源圖像由整數(shù)數(shù)組表示,其中每個整數(shù)包含單個像素的顏色值,模糊的目標(biāo)圖像也由與源相同大小的整數(shù)數(shù)組表示。

通過一次一個像素地處理源數(shù)組來完成模糊,將每個像素與其周圍像素進(jìn)行平均(對紅色、綠色和藍(lán)色組件進(jìn)行平均),并將結(jié)果放置在目標(biāo)數(shù)組中,由于圖像是大型數(shù)組,因此此過程可能需要很長時間,通過使用fork/join框架實(shí)現(xiàn)的算法,你可以利用多處理器系統(tǒng)上的并發(fā)處理,這是一個可能的實(shí)現(xiàn):

public class ForkBlur extends RecursiveAction {
    private int[] mSource;
    private int mStart;
    private int mLength;
    private int[] mDestination;
  
    // Processing window size; should be odd.
    private int mBlurWidth = 15;
  
    public ForkBlur(int[] src, int start, int length, int[] dst) {
        mSource = src;
        mStart = start;
        mLength = length;
        mDestination = dst;
    }

    protected void computeDirectly() {
        int sidePixels = (mBlurWidth - 1) / 2;
        for (int index = mStart; index < mStart + mLength; index++) {
            // Calculate average.
            float rt = 0, gt = 0, bt = 0;
            for (int mi = -sidePixels; mi <= sidePixels; mi++) {
                int mindex = Math.min(Math.max(mi + index, 0),
                                    mSource.length - 1);
                int pixel = mSource[mindex];
                rt += (float)((pixel & 0x00ff0000) >> 16)
                      / mBlurWidth;
                gt += (float)((pixel & 0x0000ff00) >>  8)
                      / mBlurWidth;
                bt += (float)((pixel & 0x000000ff) >>  0)
                      / mBlurWidth;
            }
          
            // Reassemble destination pixel.
            int dpixel = (0xff000000     ) |
                   (((int)rt) << 16) |
                   (((int)gt) <<  8) |
                   (((int)bt) <<  0);
            mDestination[index] = dpixel;
        }
    }
  
  ...

現(xiàn)在,你實(shí)現(xiàn)抽象的compute()方法,該方法可以直接執(zhí)行模糊或?qū)⑵洳鸱譃閮蓚€較小的任務(wù),簡單的數(shù)組長度閾值有助于確定是執(zhí)行還是拆分工作。

protected static int sThreshold = 100000;

protected void compute() {
    if (mLength < sThreshold) {
        computeDirectly();
        return;
    }
    
    int split = mLength / 2;
    
    invokeAll(new ForkBlur(mSource, mStart, split, mDestination),
              new ForkBlur(mSource, mStart + split, mLength - split,
                           mDestination));
}

如果以前的方法在RecursiveAction類的子類中,那么將任務(wù)設(shè)置為在ForkJoinPool中運(yùn)行是很簡單的,涉及以下步驟:

創(chuàng)建一個代表要完成的所有工作的任務(wù)。

// source image pixels are in src
// destination image pixels are in dst
ForkBlur fb = new ForkBlur(src, 0, src.length, dst);

創(chuàng)建將運(yùn)行任務(wù)的ForkJoinPool

ForkJoinPool pool = new ForkJoinPool();

運(yùn)行任務(wù)。

pool.invoke(fb);

有關(guān)完整源代碼(包括創(chuàng)建目標(biāo)圖像文件的一些額外代碼),請參閱ForkBlur示例。

標(biāo)準(zhǔn)實(shí)現(xiàn)

除了使用fork/join框架來實(shí)現(xiàn)在多處理器系統(tǒng)上同時執(zhí)行任務(wù)的自定義算法(例如ForkBlur.java示例),Java SE中已經(jīng)使用fork/join框架實(shí)現(xiàn)了一些通常有用的功能,在Java SE 8中引入的一種這樣的實(shí)現(xiàn)被java.util.Arrays類用于其parallelSort()方法,這些方法類似于sort(),但通過fork/join框架利用并發(fā)性。在多處理器系統(tǒng)上運(yùn)行時,大型數(shù)組的并行排序比順序排序更快,但是,這些方法如何利用fork/join框架超出了Java教程的范圍,有關(guān)此信息,請參閱Java API文檔。

fork/join框架的另一個實(shí)現(xiàn)由java.util.streams包中的方法使用,這是Project Lambda計劃用于Java SE 8版本的一部分,有關(guān)更多信息,請參閱Lambda表達(dá)式部分。

上一篇:Lock對象 下一篇:原子變量

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/73062.html

相關(guān)文章

  • Java 8 并發(fā)教程:線程和執(zhí)行器

    摘要:在這個示例中我們使用了一個單線程線程池的。在延遲消逝后,任務(wù)將會并發(fā)執(zhí)行。這是并發(fā)系列教程的第一部分。第一部分線程和執(zhí)行器第二部分同步和鎖第三部分原子操作和 Java 8 并發(fā)教程:線程和執(zhí)行器 原文:Java 8 Concurrency Tutorial: Threads and Executors 譯者:BlankKelly 來源:Java8并發(fā)教程:Threads和Execut...

    jsdt 評論0 收藏0
  • Java? 教程(目錄)

    Java? 教程 Java教程是為JDK 8編寫的,本頁面中描述的示例和實(shí)踐沒有利用在后續(xù)版本中引入的改進(jìn)。 Java教程是希望使用Java編程語言創(chuàng)建應(yīng)用程序的程序員的實(shí)用指南,其中包括數(shù)百個完整的工作示例和數(shù)十個課程,相關(guān)課程組被組織成教程。 覆蓋基礎(chǔ)知識的路徑 這些教程以書籍的形式提供,如Java教程,第六版,前往Amazon.com購買。 入門 介紹Java技術(shù)和安裝Java開發(fā)軟件并使用...

    lifesimple 評論0 收藏0
  • Java? 教程(進(jìn)程和線程)

    并發(fā) 計算機(jī)用戶想當(dāng)然地認(rèn)為他們的系統(tǒng)一次可以做不止一件事,他們設(shè)想他們可以繼續(xù)在文字處理器中工作,而其他應(yīng)用程序則下載文件、管理打印隊(duì)列和流音頻,即使是單個應(yīng)用程序通常也希望一次完成多個任務(wù)。例如,流式音頻應(yīng)用程序必須同時從網(wǎng)絡(luò)上讀取數(shù)字音頻、解壓縮、管理回放并更新其顯示,甚至文字處理器應(yīng)始終準(zhǔn)備好響應(yīng)鍵盤和鼠標(biāo)事件,無論重新格式化文本或更新顯示有多繁忙,可以執(zhí)行此類操作的軟件稱為并發(fā)軟件。 J...

    AZmake 評論0 收藏0
  • Java 8 并發(fā)教程:原子變量和 ConcurrentMa

    摘要:并發(fā)教程原子變量和原文譯者飛龍協(xié)議歡迎閱讀我的多線程編程系列教程的第三部分。如果你能夠在多線程中同時且安全地執(zhí)行某個操作,而不需要關(guān)鍵字或上一章中的鎖,那么這個操作就是原子的。當(dāng)多線程的更新比讀取更頻繁時,這個類通常比原子數(shù)值類性能更好。 Java 8 并發(fā)教程:原子變量和 ConcurrentMap 原文:Java 8 Concurrency Tutorial: Synchroni...

    bitkylin 評論0 收藏0
  • Java? 教程(高級并發(fā)對象)

    高級并發(fā)對象 到目前為止,本課程重點(diǎn)關(guān)注從一開始就是Java平臺一部分的低級別API,這些API適用于非常基礎(chǔ)的任務(wù),但更高級的任務(wù)需要更高級別的構(gòu)建塊,對于充分利用當(dāng)今多處理器和多核系統(tǒng)的大規(guī)模并發(fā)應(yīng)用程序尤其如此。 在本節(jié)中,我們將介紹Java平臺5.0版中引入的一些高級并發(fā)功能,大多數(shù)這些功能都在新的java.util.concurrent包中實(shí)現(xiàn),Java集合框架中還有新的并發(fā)數(shù)據(jù)結(jié)構(gòu)。 ...

    xiaotianyi 評論0 收藏0
  • [譯] Java 8 Nashorn 教程

    摘要:未來的主要發(fā)布基于。在中調(diào)用函數(shù)支持從代碼中直接調(diào)用定義在腳本文件中的函數(shù)。下面的函數(shù)稍后會在端調(diào)用為了調(diào)用函數(shù),你首先需要將腳本引擎轉(zhuǎn)換為。調(diào)用函數(shù)將結(jié)果輸出到,所以我們會首先看到輸出。幸運(yùn)的是,有一套補(bǔ)救措施。 原文:Java 8 Nashorn Tutorial 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 這個教程中,你會通過簡單易懂的代碼示例,來了解Nashorn Ja...

    _ivan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<