久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

一心多用多線程

 館天下ccf 2018-01-23

深夜學(xué)習(xí),,發(fā)現(xiàn)ThreadPoolExecutor里面一個(gè)小知識(shí)點(diǎn),,故開(kāi)熱點(diǎn)連wifi怒寫(xiě)submit與execute方法的區(qū)別,。

1.問(wèn)題的來(lái)源

在看書(shū)的時(shí)候,涉及到j(luò)ava線程池問(wèn)題的時(shí)候常常面臨這樣一個(gè)問(wèn)題,。當(dāng)定義了一個(gè)Runnable對(duì)象想提交到線程池里面總是會(huì)看到不同的提交方法,,產(chǎn)生的尬題如下:

public class ThreadPoolDemo {
    public static class MyTask implements Runnable{
        @Override
        public void run() {
            System.out.println(System.currentTimeMillis()+":Thread ID:"+Thread.currentThread().getId());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public static void main(String[] args){
            MyTask task = new MyTask();
            ExecutorService es = Executors.newCachedThreadPool();
            for(int i=0;i<10;i++){
                es.submit(task);//問(wèn)題出現(xiàn)在這里!
                es.execute(task);
            }
        }

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

明明在看上一頁(yè)書(shū)的時(shí)候,,向線程池提交任務(wù)的時(shí)候,,用的是submit()方法,等到看下一頁(yè)的時(shí)候媽蛋,怎么用成execute()了,,這兩個(gè)搞什么鬼,,同一個(gè)功能難道有兩個(gè)方法可以調(diào)用?我不精陷入了深思,,怒查java api文檔。

2.java api文檔對(duì)這兩個(gè)方法的描述

首先,,記憶里面對(duì)execute()方法是記憶比較深刻的,,故查了一下該方法的api文檔,發(fā)現(xiàn)信息如下:

  • execute() 是在Executor接口中定義的,,ThreadPoolExecutor繼承了AbstractExecutorService抽象類(lèi),,該抽象類(lèi)實(shí)現(xiàn)了ExecutorService接口(但并沒(méi)有覆蓋execute方法),而ExecutorService接口繼承了Executor接口,。

簡(jiǎn)而言之就是說(shuō)ThreadPoolExecutor實(shí)現(xiàn)了execute()方法,。然后我們來(lái)看看api文檔對(duì)execute()方法是如何定義的:

execute public void execute(Runnable command)
在將來(lái)某個(gè)時(shí)間執(zhí)行給定任務(wù)??梢栽谛戮€程中或者在現(xiàn)有池線程中執(zhí)行該任務(wù),。如果無(wú)法將任務(wù)提交執(zhí)行,或者因?yàn)榇藞?zhí)行程序已關(guān)閉,,或者因?yàn)橐堰_(dá)到其容量,,則該任務(wù)由當(dāng)前 RejectedExecutionHandler處理。

參數(shù): command - 要執(zhí)行的任務(wù),。 拋出: RejectedExecutionException -
如果無(wú)法接收要執(zhí)行的任務(wù),,則由 RejectedExecutionHandler 決定是否拋出
RejectedExecutionException NullPointerException - 如果命令為 null

看的是我一蒙一蒙的,主要是”在將來(lái)某個(gè)時(shí)間執(zhí)行給定任務(wù),?!边@一句讓我很費(fèi)解,所以我決定再看看submit()方法是怎么寫(xiě)的,。

  • submit方法是ExecutorService接口里面定義的,,具體的實(shí)現(xiàn)由AbstractExecutorService進(jìn)行。

submit方法被重載了三次,,分別對(duì)用三個(gè)不同的參數(shù),。對(duì)api摘錄如下:

submit public Future<?> submit(Runnable task)

提交一個(gè) Runnable 任務(wù)用于執(zhí)行,,并返回一個(gè)表示該任務(wù)的 Future,。該 Future 的 get 方法在成功 完成時(shí)將會(huì)返回null。

指定者: 接口 ExecutorService 中的 submit 參數(shù): task - 要提交的任務(wù) 返回: 表示任務(wù)等待完成的 Future


submit public Future submit(Runnable task,T result) 提交一個(gè)
Runnable 任務(wù)用于執(zhí)行,,并返回一個(gè)表示該任務(wù)的 Future,。該 Future 的 get 方法在成功完成時(shí)將會(huì)返回給定的結(jié)果。

指定者: 接口 ExecutorService 中的 submit 參數(shù): task - 要提交的任務(wù) result - 返回的結(jié)果
返回: 表示任務(wù)等待完成的 Future


submit public Future submit(Callable task)
提交一個(gè)返回值的任務(wù)用于執(zhí)行,返回一個(gè)表示任務(wù)的未決結(jié)果的 Future,。該 Future 的 get
方法在成功完成時(shí)將會(huì)返回該任務(wù)的結(jié)果,。 如果想立即阻塞任務(wù)的等待,則可以使用 result =
exec.submit(aCallable).get(); 形式的構(gòu)造,。

注:Executors 類(lèi)包括了一組方法,,可以轉(zhuǎn)換某些其他常見(jiàn)的類(lèi)似于閉包的對(duì)象,例如,,將 PrivilegedAction 轉(zhuǎn)換為Callable 形式,,這樣就可以提交它們了。

指定者: 接口 ExecutorService 中的 submit 參數(shù): task - 要提交的任務(wù) 返回: 表示任務(wù)等待完成的Future

如上所示,,第二個(gè)與第三個(gè)可以理解,,不就是我記錄過(guò)的Future模式里面的那一套東西嗎?就是說(shuō)execute不支持Future這一套,,而submit支持一套并可以返回一個(gè)Future給你到后面獲取結(jié)果的時(shí)候可以get一get,。

但是看到第一個(gè)的時(shí)候我又蒙蔽了,”提交一個(gè) Runnable 任務(wù)用于執(zhí)行,,并返回一個(gè)表示該任務(wù)的 Future,。該 Future 的 get 方法在成功 完成時(shí)將會(huì)返回null?!眿尩?,那這樣與execute又有什么區(qū)別呀。何必這樣多此一舉呢,?我不服,,我認(rèn)為execute與submit里面肯定存在互相調(diào)用的關(guān)系,畢竟ExecutorService是Executor的子類(lèi)嘛

3.怒開(kāi)IDE,,深入源碼一探究竟

寫(xiě)了一個(gè)線程池,,ctrl+左鍵深入execute方法,發(fā)現(xiàn)代碼如下:

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

這不是關(guān)于任務(wù)到線程池里面一些具體的操作嗎!菜鳥(niǎo)太菜有些方法還是深入理解不了,,不談,。回到剛剛想的那個(gè)問(wèn)題,,這樣的話那么execute方法就是具體對(duì)任務(wù)的操作,,那么submit方法呢?

點(diǎn)擊進(jìn)入了AbstractExecutorService抽象類(lèi)源代碼,,發(fā)現(xiàn)源碼如下:

    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }


    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }

    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

這媽蛋,,不是都把拿到的Runnable任務(wù)都構(gòu)造了RunnableFuture任務(wù)然后都拋給execute方法嗎!也是醉了,,
得出結(jié)論1:如果提交的任務(wù)不需要一個(gè)結(jié)果的話直接用execute()會(huì)提升很多性能,。

那我奇怪了newTaskFor這個(gè)又是什么jb玩意啊,,用這個(gè)函數(shù)是怎么構(gòu)造一個(gè)RunnableFuture任務(wù)的,怒氣又來(lái)進(jìn)入了方法,,得結(jié)果如下:

    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

罵了個(gè)比啊,,這個(gè)方法不是幫你new了FutureTask嗎!氣得我得出

結(jié)論二:就是相當(dāng)于說(shuō)如果你傳的任務(wù)是需要結(jié)果的,,那你就使用你的類(lèi)去繼承Callable接口,,然后告訴submit方法就行了,如果你只需要一個(gè)特定的結(jié)果,,就把那個(gè)特定的結(jié)果告訴submit方法然后把你想要的特定結(jié)果也告訴他,,它只是幫你完成以前使用Future模式的時(shí)候你自己需要做的那些步驟而已,如果你不需要一個(gè)結(jié)果,,那么就老老實(shí)實(shí)使用execute,,如果你需要的是一個(gè)空結(jié)果,,那么submit(yourRunnable)與submit(yourRunnable,null)是等價(jià)的,! 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多