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

資訊專欄INFORMATION COLUMN

java-AQS源碼淺析

Lemon_95 / 2795人閱讀

摘要:獲取資源失敗,將該線程加入等待隊(duì)列尾部,標(biāo)記為獨(dú)占模式。如果有剩余資源則會(huì)喚醒下一個(gè)線程,且整個(gè)過(guò)程忽略中斷的影響。

AQS概念及定義

ASQ:AbstractQueuedSynchronizer

它維護(hù)了一個(gè)volatile int state(代表共享資源)和一個(gè)FIFO線程等待隊(duì)列(多線程爭(zhēng)用資源被阻塞時(shí)會(huì)進(jìn)入此隊(duì)列,有個(gè)內(nèi)部類Node定義了節(jié)點(diǎn)。隊(duì)列由AQS的volatile成員變量head和tail組成一個(gè)雙向鏈表)

資源共享方式

AQS定義兩種資源共享方式:Exclusive(獨(dú)占,只有一個(gè)線程能執(zhí)行,如ReentrantLock)和Share(共享,多個(gè)線程可同時(shí)執(zhí)行,如Semaphore/CountDownLatch)。

自定義同步器

AQS是抽象類,使用了模板方法設(shè)計(jì)模式,已經(jīng)將流程定義好,且實(shí)現(xiàn)了對(duì)等待隊(duì)列的維護(hù),因此實(shí)現(xiàn)者只需要按需實(shí)現(xiàn)AQS預(yù)留的四個(gè)方法即可。

isHeldExclusively():該線程是否正在獨(dú)占資源。只有用到condition才需要去實(shí)現(xiàn)它。

tryAcquire(int):獨(dú)占方式。嘗試獲取資源,成功則返回true,失敗則返回false。

tryRelease(int):獨(dú)占方式。嘗試釋放資源,成功則返回true,失敗則返回false。

tryAcquireShared(int):共享方式。嘗試獲取資源。負(fù)數(shù)表示失敗;0表示成功,但沒有剩余可用資源;正數(shù)表示成功,且有剩余資源。

tryReleaseShared(int):共享方式。嘗試釋放資源,如果釋放后允許喚醒后續(xù)等待結(jié)點(diǎn)返回true,否則返回false。

一般來(lái)說(shuō),自定義同步器要么是獨(dú)占方法,要么是共享方式,他們也只需實(shí)現(xiàn)tryAcquire-tryRelease、tryAcquireShared-tryReleaseShared中的一種即可。但AQS也支持自定義同步器同時(shí)實(shí)現(xiàn)獨(dú)占和共享兩種方式,如ReentrantReadWriteLock。

核心方法分析

1.1 acquire(int)

方法定義

此方法是獨(dú)占模式下線程獲取共享資源的頂層入口。如果獲取到資源,線程直接返回,否則進(jìn)入等待隊(duì)列,直到獲取到資源為止,且整個(gè)過(guò)程忽略中斷的影響。

方法源碼
    /**
     * Acquires in exclusive mode, ignoring interrupts.  Implemented
     * by invoking at least once {@link #tryAcquire},
     * returning on success.  Otherwise the thread is queued, possibly
     * repeatedly blocking and unblocking, invoking {@link
     * #tryAcquire} until success.  This method can be used
     * to implement method {@link Lock#lock}.
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquire} but is otherwise uninterpreted and
     *        can represent anything you like.
     */
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
函數(shù)流程
1. tryAcquire():嘗試獲取資源。
2. addWaiter(Node.EXCLUSIVE):獲取資源失敗,將該線程加入等待隊(duì)列尾部,標(biāo)記為獨(dú)占模式。
3. acquireQueued(Node,int):獲取該node指定數(shù)量的資源數(shù),會(huì)一直等待成功獲取才返回,返回值是在獲取期間是否中斷過(guò)
源碼分析

1. tryAcquire()

  /**
     * Attempts to acquire in exclusive mode. This method should query
     * if the state of the object permits it to be acquired in the
     * exclusive mode, and if so to acquire it.
     *
     * 

This method is always invoked by the thread performing * acquire. If this method reports failure, the acquire method * may queue the thread, if it is not already queued, until it is * signalled by a release from some other thread. This can be used * to implement method {@link Lock#tryLock()}. * *

The default * implementation throws {@link UnsupportedOperationException}. * * @param arg the acquire argument. This value is always the one * passed to an acquire method, or is the value saved on entry * to a condition wait. The value is otherwise uninterpreted * and can represent anything you like. * @return {@code true} if successful. Upon success, this object has * been acquired. * @throws IllegalMonitorStateException if acquiring would place this * synchronizer in an illegal state. This exception must be * thrown in a consistent fashion for synchronization to work * correctly. * @throws UnsupportedOperationException if exclusive mode is not supported */ protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); }

這是個(gè)抽象方法,用于給實(shí)現(xiàn)者自定義實(shí)現(xiàn),此方法嘗試去獲取獨(dú)占資源。如果獲取成功,則直接返回true,否則直接返回false。這也正是tryLock()的語(yǔ)義。

2. addWaiter(Node)

/**
     * Creates and enqueues node for current thread and given mode.
     *
     * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
     * @return the new node
     */
    private Node addWaiter(Node mode) {
        //新建Node
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        //快速嘗試一次,使用CAS將node放到隊(duì)尾,失敗調(diào)用enq
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        //保證將Node放入隊(duì)尾
        enq(node);
        return node;
    }

enq源碼

/**
     * Inserts node into queue, initializing if necessary. See picture above.
     * @param node the node to insert
     * @return node"s predecessor
     */
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            //如果尾節(jié)點(diǎn)為空,說(shuō)明隊(duì)列還未進(jìn)行初始化
            if (t == null) { // Must initialize
                //CAS設(shè)置頭結(jié)點(diǎn)
                if (compareAndSetHead(new Node()))
                    //初始頭尾相同,從下一次循環(huán)開始嘗試加入新Node
                    tail = head;
            } else {
                node.prev = t;
                //CAS將當(dāng)前節(jié)點(diǎn)設(shè)置為尾節(jié)點(diǎn)
                if (compareAndSetTail(t, node)) {
                    //設(shè)置成功返回當(dāng)前節(jié)點(diǎn)
                    t.next = node;
                    return t;
                }
            }
        }
    }

3. acquireQueued(Node, int)

/**
     * Acquires in exclusive uninterruptible mode for thread already in
     * queue. Used by condition wait methods as well as acquire.
     *
     * @param node the node
     * @param arg the acquire argument
     * @return {@code true} if interrupted while waiting
     */
    final boolean acquireQueued(final Node node, int arg) {
        //標(biāo)志是否成功獲取資源
        boolean failed = true;
        try {
            //是否被中斷
            boolean interrupted = false;
            for (;;) {
                //獲取前驅(qū)Node
                final Node p = node.predecessor();
                //如果自己是隊(duì)列中第二個(gè)節(jié)點(diǎn),那會(huì)進(jìn)行嘗試獲取,進(jìn)入這里判斷要么是一次,要么是被前驅(qū)節(jié)點(diǎn)給unPark喚醒了。
                if (p == head && tryAcquire(arg)) {
                    //成功獲取資源,設(shè)置自身為頭節(jié)點(diǎn),將原來(lái)的頭結(jié)點(diǎn)剝離隊(duì)列
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                //判斷是否需要被park,如果需要進(jìn)行park并檢測(cè)是否被中斷
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            //如果獲取資源失敗了將當(dāng)前node取消,
            if (failed)
                cancelAcquire(node);
        }
    }

shouldParkAfterFailedAcquire方法

/**
     * Checks and updates status for a node that failed to acquire.
     * Returns true if thread should block. This is the main signal
     * control in all acquire loops.  Requires that pred == node.prev.
     *
     * @param pred node"s predecessor holding status
     * @param node the node
     * @return {@code true} if thread should block
     */
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        //如果前驅(qū)的狀態(tài)已經(jīng)是signal,代表前驅(qū)釋放是會(huì)通知喚醒你,那么此node可以安心被park
        if (ws == Node.SIGNAL)
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             */
            return true;
        if (ws > 0) {
            /*
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             */
             //如果前驅(qū)已經(jīng)被取消,那么從當(dāng)前node一直往前找,直到有非取消的node,直接排在它的后面,此時(shí)不需要park,會(huì)出去再嘗試一次獲取資源。
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don"t park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             */
             //前驅(qū)節(jié)點(diǎn)沒有被取消,那么告訴前驅(qū)節(jié)點(diǎn)釋放的時(shí)候通知自己
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

parkAndCheckInterrupt()

/**
     * Convenience method to park and then check if interrupted
     *
     * @return {@code true} if interrupted
     */
    private final boolean parkAndCheckInterrupt() {
        //讓該線程進(jìn)入wait狀態(tài)
        LockSupport.park(this);
        //返回期間是被中斷過(guò)
        return Thread.interrupted();
    }

acquireQueued流程總結(jié)

檢查自己是否是老二,且是否能獲得資源,能獲得自己成為head節(jié)點(diǎn),否則進(jìn)入流程2。

2.找到“有效”(not canceled)的前驅(qū),并通知前驅(qū)釋放了要“通知”(watiStatus=signal)我,安心被park。
3。被前驅(qū)unpark,或interrrupt(),繼續(xù)流程1。

acquire小結(jié)

首先調(diào)用實(shí)現(xiàn)者實(shí)現(xiàn)的tryAcquire()去獲取資源,如果成功則直接返回。

如果失敗,則新建一個(gè)獨(dú)占模式的節(jié)點(diǎn)加到隊(duì)列尾部。

通知一個(gè)有效的前驅(qū)記得釋放時(shí)喚醒自己,在喚醒時(shí)自己再進(jìn)行不斷tryAcquire()直到獲取到資源,返回是否被中斷過(guò)。

如果等待過(guò)程中被中斷過(guò),則將將中斷補(bǔ)上,調(diào)用當(dāng)前線程的interrupt().

至此acquire流程完結(jié),

1.2 release(int)

方法定義

此方法是獨(dú)占模式下線程釋放共享資源的頂層入口。它會(huì)釋放指定量的資源,如果徹底釋放了(即state=0),它會(huì)喚醒等待隊(duì)列里的其他線程來(lái)獲取資源。這也正是unlock()的語(yǔ)義。

方法源碼
   /**
     * Releases in exclusive mode.  Implemented by unblocking one or
     * more threads if {@link #tryRelease} returns true.
     * This method can be used to implement method {@link Lock#unlock}.
     *
     * @param arg the release argument.  This value is conveyed to
     *        {@link #tryRelease} but is otherwise uninterpreted and
     *        can represent anything you like.
     * @return the value returned from {@link #tryRelease}
     */
    public final boolean release(int arg) {
        //調(diào)用實(shí)現(xiàn)者的嘗試解鎖方法,因?yàn)橐呀?jīng)獲得鎖,所以基本不會(huì)失敗
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                //喚醒下一個(gè)節(jié)點(diǎn)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

unparkSuccessor()

 /**
     * Wakes up node"s successor, if one exists.
     *
     * @param node the node
     */
    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        int ws = node.waitStatus;
        if (ws < 0)//設(shè)置當(dāng)前節(jié)點(diǎn)的狀態(tài)允許失敗,失敗了也沒關(guān)系。
            compareAndSetWaitStatus(node, ws, 0);

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
         //找到下一個(gè)需要被喚醒的節(jié)點(diǎn)
        Node s = node.next;
        if (s == null || s.waitStatus > 0) {//如果是空或被取消
            s = null;
            //從尾節(jié)點(diǎn)開始尋找,直到找到最前面的有效的節(jié)點(diǎn)。因?yàn)殒i已經(jīng)釋放,所以從尾節(jié)點(diǎn)開始找可以避免因?yàn)楦卟l(fā)下復(fù)雜的隊(duì)列動(dòng)態(tài)變化帶來(lái)的邏輯判斷,
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        if (s != null)
            LockSupport.unpark(s.thread);
    }
release小結(jié)

首先調(diào)用實(shí)現(xiàn)者的tryRelease(),失敗則返回false

成功則找到下一個(gè)有效的節(jié)點(diǎn)并喚醒它。

注意實(shí)現(xiàn)者實(shí)現(xiàn)tryRelease應(yīng)該是當(dāng)state為0時(shí)才返回

1.3 acquireShared(int)

方法定義

此方法是共享模式下線程獲取共享資源的頂層入口。如果獲取到資源,線程直接返回。如果有剩余資源則會(huì)喚醒下一個(gè)線程,否則進(jìn)入wait,且整個(gè)過(guò)程忽略中斷的影響。

方法源碼
    /**
     * Acquires in shared mode, ignoring interrupts.  Implemented by
     * first invoking at least once {@link #tryAcquireShared},
     * returning on success.  Otherwise the thread is queued, possibly
     * repeatedly blocking and unblocking, invoking {@link
     * #tryAcquireShared} until success.
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquireShared} but is otherwise uninterpreted
     *        and can represent anything you like.
     */
    public final void acquireShared(int arg) {
        //嘗試獲取指定數(shù)量資源
        if (tryAcquireShared(arg) < 0)
            //獲取資源直到成功
            doAcquireShared(arg);
    }

共享模式下的流程與獨(dú)占模式極為相似,首先根據(jù)tryAcquireShared(arg)嘗試是否能獲取到資源,能則直接返回,不能則會(huì)進(jìn)入隊(duì)列按入隊(duì)順序依次喚醒嘗試獲取。

tryAcquireShared(int)

/**
     * Attempts to acquire in shared mode. This method should query if
     * the state of the object permits it to be acquired in the shared
     * mode, and if so to acquire it.
     *
     * 

This method is always invoked by the thread performing * acquire. If this method reports failure, the acquire method * may queue the thread, if it is not already queued, until it is * signalled by a release from some other thread. * *

The default implementation throws {@link * UnsupportedOperationException}. * * @param arg the acquire argument. This value is always the one * passed to an acquire method, or is the value saved on entry * to a condition wait. The value is otherwise uninterpreted * and can represent anything you like. * @return a negative value on failure; zero if acquisition in shared * mode succeeded but no subsequent shared-mode acquire can * succeed; and a positive value if acquisition in shared * mode succeeded and subsequent shared-mode acquires might * also succeed, in which case a subsequent waiting thread * must check availability. (Support for three different * return values enables this method to be used in contexts * where acquires only sometimes act exclusively.) Upon * success, this object has been acquired. * @throws IllegalMonitorStateException if acquiring would place this * synchronizer in an illegal state. This exception must be * thrown in a consistent fashion for synchronization to work * correctly. * @throws UnsupportedOperationException if shared mode is not supported */ protected int tryAcquireShared(int arg) { throw new UnsupportedOperationException(); }

這是AQS預(yù)留給實(shí)現(xiàn)者的方法,用于共享模式下嘗試獲取指定數(shù)量的資源,返回值<0代表獲取失敗,=0代表獲取成功且無(wú)剩余資源,>0代表還有剩余資源

doAcquireShared(int)方法用于共享模式獲取資源會(huì)直到獲取成功才返回

/**
     * Acquires in shared uninterruptible mode.
     * @param arg the acquire argument
     */
    private void doAcquireShared(int arg) {
        //添加當(dāng)前線程的Node模式為共享模式至隊(duì)尾,
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                //獲取前驅(qū)節(jié)點(diǎn)
                final Node p = node.predecessor();
                //如果自己是老二才有嘗試的資格
                if (p == head) {
                    //嘗試獲取指定數(shù)量資源
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        //如果成功獲取,將當(dāng)前節(jié)點(diǎn)設(shè)置為頭節(jié)點(diǎn),如果有剩余資源喚醒下一有效節(jié)點(diǎn)
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        //如果有中斷,自己補(bǔ)償中斷
                        if (interrupted)
                            selfInterrupt();
                        failed = false;
                        return;
                    }
                }
                //判斷是否需要被park,和park后檢查是否被中弄斷
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            //如果獲取失敗,取消當(dāng)前節(jié)點(diǎn)
            if (failed)
                cancelAcquire(node);
        }
    }

流程和獨(dú)占模式幾乎一模一樣,但是代碼的書寫缺有不同,不知原作者是咋想的。區(qū)別于獨(dú)占不同的有兩點(diǎn)

添加模式為SHARED1的Node。

在成功獲取到資源后,設(shè)置當(dāng)前節(jié)點(diǎn)為head節(jié)點(diǎn)時(shí),如果還有剩余資源的話,會(huì)喚醒下一個(gè)有效的節(jié)點(diǎn),如果資源數(shù)量不夠下一節(jié)點(diǎn),下一節(jié)點(diǎn)會(huì)一直等待,直到其它節(jié)點(diǎn)釋放,并不會(huì)讓步給后面的節(jié)點(diǎn),取決于FIFO的按順序出隊(duì)。

setHeadAndPropagate()看有剩余資源的時(shí)候如何喚醒下一節(jié)點(diǎn)

/**
     * Sets head of queue, and checks if successor may be waiting
     * in shared mode, if so propagating if either propagate > 0 or
     * PROPAGATE status was set.
     *
     * @param node the node
     * @param propagate the return value from a tryAcquireShared
     */
    private void setHeadAndPropagate(Node node, int propagate) {
        Node h = head; // Record old head for check below
        //將當(dāng)前節(jié)點(diǎn)設(shè)置為head節(jié)點(diǎn)
        setHead(node);
        /*
         * Try to signal next queued node if:
         *   Propagation was indicated by caller,
         *     or was recorded (as h.waitStatus either before
         *     or after setHead) by a previous operation
         *     (note: this uses sign-check of waitStatus because
         *      PROPAGATE status may transition to SIGNAL.)
         * and
         *   The next node is waiting in shared mode,
         *     or we don"t know, because it appears null
         *
         * The conservatism in both of these checks may cause
         * unnecessary wake-ups, but only when there are multiple
         * racing acquires/releases, so most need signals now or soon
         * anyway.
         */
         //如果有剩余資源
        if (propagate > 0 || h == null || h.waitStatus < 0 ||
            (h = head) == null || h.waitStatus < 0) {
            Node s = node.next;
            //當(dāng)下一個(gè)有效節(jié)點(diǎn)存在且是共享模式時(shí),會(huì)喚醒它
            if (s == null || s.isShared())
                doReleaseShared();
        }
    }

doReleaseShared()喚醒下一共享模式節(jié)點(diǎn)

/**
     * Release action for shared mode -- signals successor and ensures
     * propagation. (Note: For exclusive mode, release just amounts
     * to calling unparkSuccessor of head if it needs signal.)
     */
    private void doReleaseShared() {
        /*
         * Ensure that a release propagates, even if there are other
         * in-progress acquires/releases.  This proceeds in the usual
         * way of trying to unparkSuccessor of head if it needs
         * signal. But if it does not, status is set to PROPAGATE to
         * ensure that upon release, propagation continues.
         * Additionally, we must loop in case a new node is added
         * while we are doing this. Also, unlike other uses of
         * unparkSuccessor, we need to know if CAS to reset status
         * fails, if so rechecking.
         */
        for (;;) {
            Node h = head;
            if (h != null && h != tail) {
                int ws = h.waitStatus;
                //如果頭結(jié)點(diǎn)狀態(tài)是“通知后繼”
                if (ws == Node.SIGNAL) {
                    //將其狀態(tài)改為0,表示已通知
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                        continue;            // loop to recheck cases
                    //喚醒后繼
                    unparkSuccessor(h);
                }
                //如果已通知后繼,則改為可傳播,在下次acquire中的shouldParkAfterFailedAcquire會(huì)將改為SIGNAL
                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue;                // loop on failed CAS
            }
            //如果頭結(jié)點(diǎn)變了,再次循環(huán)
            if (h == head)                   // loop if head changed
                break;
        }
    }
acquireShared小結(jié)

共享模式acquire與獨(dú)占模式技術(shù)相同,唯一的不同就是在于如果當(dāng)前節(jié)點(diǎn)獲取資源成功且有剩余則會(huì)喚醒下一節(jié)點(diǎn),資源可以為多個(gè)線程功能分配,而獨(dú)占模式則就是一個(gè)線程獨(dú)占。

1.4 releaseShared(int)

方法定義

此方法是共享模式下線程釋放共享資源的頂層入口。如果釋放資源成功,直接返回。如果有剩余資源則會(huì)喚醒下一個(gè)線程,且整個(gè)過(guò)程忽略中斷的影響。

方法源碼
/**
     * Releases in shared mode.  Implemented by unblocking one or more
     * threads if {@link #tryReleaseShared} returns true.
     *
     * @param arg the release argument.  This value is conveyed to
     *        {@link #tryReleaseShared} but is otherwise uninterpreted
     *        and can represent anything you like.
     * @return the value returned from {@link #tryReleaseShared}
     */
    public final boolean releaseShared(int arg) {
        //嘗試共享模式獲取資源
        if (tryReleaseShared(arg)) {
            //喚醒下一節(jié)點(diǎn)
            doReleaseShared();
            return true;
        }
        return false;
    }
AQS的源碼分析就到這里為止由于本人目前功力尚淺,對(duì)AQS的理解停留在代碼級(jí)別,下此會(huì)將應(yīng)用補(bǔ)上,如有不對(duì)和遺漏歡迎各位補(bǔ)充。

參考文章
Java并發(fā)之AQS詳解

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

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

相關(guān)文章

  • 淺析webpack源碼之前言(一)

    為什么讀webpack源碼 因?yàn)榍岸丝蚣茈x不開webpack,天天都在用的東西啊,怎能不研究 讀源碼能學(xué)到很多做項(xiàng)目看書學(xué)不到的東西,比如說(shuō)架構(gòu),構(gòu)造函數(shù),es6很邊緣的用法,甚至給函數(shù)命名也會(huì)潛移默化的影響等 想寫源碼,不看源碼怎么行,雖然現(xiàn)在還不知道寫什么,就算不寫什么,看看別人寫的總可以吧 知道世界的廣闊,那么多插件,那么多軟件開發(fā)師,他們?cè)谧鍪裁矗瑯邮菍慾s的,怎么他們能這么偉大 好奇...

    suosuopuo 評(píng)論0 收藏0
  • 淺析HashMap源碼(1)

    摘要:前言本文的目的是閱讀理解的源碼,作為集合中重要的一個(gè)角色,平時(shí)用到十分多的一個(gè)類,深入理解它,知其所以然很重要。 前言 本文的目的是閱讀理解HashMap的源碼,作為集合中重要的一個(gè)角色,平時(shí)用到十分多的一個(gè)類,深入理解它,知其所以然很重要。本文基于Jdk1.7,因?yàn)镴dk1.8改變了HashMap的數(shù)據(jù)結(jié)構(gòu),進(jìn)行了優(yōu)化,我們先從基礎(chǔ)閱讀,之后再閱讀理解Jdk1.8的內(nèi)容 HashMa...

    wwolf 評(píng)論0 收藏0
  • 淺析`redux-thunk`中間件源碼

    摘要:大多的初學(xué)者都會(huì)使用中間件來(lái)處理異步請(qǐng)求,其理解簡(jiǎn)單使用方便具體使用可參考官方文檔。源碼的源碼非常簡(jiǎn)潔,出去空格一共只有行,這行中如果不算上則只有行。官方文檔中的一節(jié)講解的非常好,也確實(shí)幫我理解了中間件的工作原理,非常推薦閱讀。 總覺得文章也應(yīng)該是有生命力的,歡迎關(guān)注我的Github上的博客,這里的文章會(huì)依據(jù)我本人的見識(shí),逐步更新。 大多redux的初學(xué)者都會(huì)使用redux-thunk...

    wing324 評(píng)論0 收藏0
  • 淺析es6-promise源碼

    摘要:主要邏輯本質(zhì)上還是回調(diào)函數(shù)那一套。通過(guò)的判斷完成異步和同步的區(qū)分。 主要邏輯: 本質(zhì)上還是回調(diào)函數(shù)那一套。通過(guò)_subscribers的判斷完成異步和同步的區(qū)分。通過(guò) resolve,reject -> publish -> invokeCallback -> resolve,reject的遞歸和下一條then的parent是上一條的child來(lái)完成then鏈的流轉(zhuǎn) 同步情況...

    fox_soyoung 評(píng)論0 收藏0
  • 淺析webpack源碼之NodeEnvironmentPlugin模塊總覽(六)

    摘要:進(jìn)入傳入地址出來(lái)一個(gè)復(fù)雜對(duì)象把掛載到對(duì)象上太復(fù)雜我們先看可以緩存輸入的文件系統(tǒng)輸入文件系統(tǒng)輸出文件系統(tǒng),掛載到對(duì)象傳入輸入文件,監(jiān)視文件系統(tǒng),掛載到對(duì)象添加事件流打開插件讀取目錄下文件對(duì)文件名進(jìn)行格式化異步讀取目錄下文件同步方法就 進(jìn)入webpack.js //傳入地址,new Compiler出來(lái)一個(gè)復(fù)雜對(duì)象 compiler = new Compiler(options.conte...

    ChristmasBoy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<