精华内容
下载资源
问答
  • 我们都知道, 在使用多线程编程的时候,每个线程运行的顺序都是随机的, 它由CPU的线程调度机制决定执行哪个线程; 我们可以看看正常使用多线程编程时程序的运行顺序: import java.util.ArrayList; import java.util....

    我们都知道, 在使用多线程编程的时候,每个线程运行的顺序都是随机的, 它由CPU的线程调度机制决定执行哪个线程;
    我们可以看看正常使用多线程编程时程序的运行顺序:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class CountDownLatchTest {
    
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            //CountDownLatch countDownLatch = new CountDownLatch(3);
            try {
                for (int i = 0; i < 3; i++) {
    
                    executorService.submit(new Callable<List<String>>() {
    
                        @Override
                        public List<String> call() throws Exception {
                            try {
                                //doSomeThing()
                                //Thread.sleep(1000);
                                System.out.println(Thread.currentThread().getName() + "线程开始执行");
                            } catch (Exception e) {
    
                            } finally {
                               //countDownLatch.countDown();
    
                            }
                            return new ArrayList<>();
    
                        }
    
                    });
                }
    
                //countDownLatch.await();
                //System.out.println("主线程执行");
    
                executorService.submit(new Callable<List<String>>() {
    
                    @Override
                    public List<String> call() throws Exception {
                        try {
                            //doSomeThing()
                            //countDownLatch.await();
                            System.out.println("测试线程开始执行");
                        } catch (Exception e) {
    
                        } finally {
    
                        }
                        return new ArrayList<>();
    
                    }
    
                });
    
            } catch (Exception e) {
    
            }finally {
                executorService.shutdown();
            }
    
        }
    }
    
    
    

    执行结果:
    在这里插入图片描述
    在这里插入图片描述
    可以看到,线程的执行顺序是随机的,他们执行的顺序并不固定.
    那么现在有一个需求, 我想让测试线程必须执行在其他三个线程执行完毕之后才执行, 也就是测试线程必须执行在其他三个线程的后面. 该怎么实现呢?

    有一个通俗一点的例子: 有三个工人在为老板干活,这个老板有一个习惯,就是当三个工人把一天的活都干完了的时候,他就来检查所有工人所干的活。记住这个条件:三个工人先全部干完活,老板才检查。
    如何实现以上的需求呢?

    CountDownLatch

    CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。

    CountDownLatch有两个核心的方法, countDown()和await()方法.在使用CountDownLatch的时候, 必须要传入一个数值型参数作为计数器的值. 调用countDown()方法可以将值减1. 而调用了await()方法的线程,在计数器的值为0之前, 会被一直阻塞. 直到计数器的值为0时才会被唤醒. 因此.可以通过CountDownLatch来实现某个线程在其他线程执行完毕之后再执行.

    那么使用CountDownLatch之后会怎么样呢?

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class CountDownLatchTest {
    
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
             //初始化CountDownLatch 计数器的值
            CountDownLatch countDownLatch = new CountDownLatch(3);
            try {
                for (int i = 0; i < 3; i++) {
    //创建三个线程, 每个线程执行完后调用countDownLatch 对象的countDown()方法将计数器减1
                    executorService.submit(new Callable<List<String>>() {
    
                        @Override
                        public List<String> call() throws Exception {
                            try {
                                //doSomeThing()
                                Thread.sleep(1000);
                                System.out.println(Thread.currentThread().getName() + "线程开始执行");
                            } catch (Exception e) {
    
                            } finally {
                               countDownLatch.countDown();
    
                            }
                            return new ArrayList<>();
    
                        }
    
                    });
                }
                
                executorService.submit(new Callable<List<String>>() {
    
                    @Override
                    public List<String> call() throws Exception {
                        try {
                            //doSomeThing()
                            //当计数器的值变为0之后,调用同一个countDownLatch对象的await()方法的主线程将会被唤醒
                            countDownLatch.await();
                            System.out.println("测试线程开始执行");
                        } catch (Exception e) {
    
                        } finally {
    
                        }
                        return new ArrayList<>();
    
                    }
    
                });
    
            } catch (Exception e) {
    
            }finally {
                executorService.shutdown();
            }
    
        }
    }
    
    

    执行结果:
    在这里插入图片描述
    在这里插入图片描述
    可以看到, 测试线程都是在前三个线程执行完毕之后才执行的
    如上面的代码中所示. 测试线程在计数器的值变为0之前, 会一直处于阻塞状态.只有当计数器值变为0时才会被唤醒. 也就是说, 测试线程是必须要运行在前三个线程之后的.

    了解到CountDownLatch的作用以及使用机制之后, 我们可以看看源码,看看CountDownLatch是如何实现阻塞测试线程, 并且在计数器为0时再唤醒测试线程的.

    CountDownLatch: wait()方法:

           
    
             public void await() throws InterruptedException {
             sync.acquireSharedInterruptibly(1);
             }
    
             public final void acquireSharedInterruptibly(int arg)
             throws InterruptedException {
             if (Thread.interrupted())
             throw new InterruptedException();
             if (tryAcquireShared(arg) < 0)	//计数器state不等于0时
             doAcquireSharedInterruptibly(arg);	//阻塞线程
             }
    
             protected int tryAcquireShared(int acquires) {
             return (getState() == 0) ? 1 : -1;
             }
    
             private void doAcquireSharedInterruptibly(int arg)
             throws InterruptedException {
             final Node node = addWaiter(Node.SHARED);//1. 将该线程加入阻塞队列中
             boolean failed = true;
             try {
             for (;;) {
             final Node p = node.predecessor();//获取前一个节点
             if (p == head) {
             int r = tryAcquireShared(arg);//2. 判断state是否为0; r>=0说明为0
             if (r >= 0) {
             //把当前节点设置成head节点,并传播 唤醒 所有被await()方法阻塞的节点
             setHeadAndPropagate(node, r);
             p.next = null; // help GC
             failed = false;
             return;
             }
             }
    
             //2. 到此处,说明state != 0
             //检查是否应该阻塞节点
             if (shouldParkAfterFailedAcquire(p, node) &&
             //阻塞节点
             parkAndCheckInterrupt())
             throw new InterruptedException();
             }
             } finally {
             if (failed)
             cancelAcquire(node);
             }
             }
    
             await()流程:
             判断state(即计数器的数量是否等于0)
             不等于0则将线程加入阻塞队列中
             等于0则唤醒所有被await()方法阻塞的线程
    

    我们来看看CountDownLatch类的结构:
    在这里插入图片描述
    可以看到CountDownLatch类中有一个继承自AQS抽象类的Sync类. AQS中实现了对同步代码中的各类操作.

    先从await()方法看起:

             public void await() throws InterruptedException {
             sync.acquireSharedInterruptibly(1);
             }
    
    

    可以看到,await()方法中调用了Sync的acquireSharedInterruptibly(1)方法;
    acquireSharedInterruptibly()方法:

             public final void acquireSharedInterruptibly(int arg)
             throws InterruptedException {
             if (Thread.interrupted())
             throw new InterruptedException();
             if (tryAcquireShared(arg) < 0)	//计数器state不等于0时
             doAcquireSharedInterruptibly(arg);	//阻塞线程
             }
    
             protected int tryAcquireShared(int acquires) {
             return (getState() == 0) ? 1 : -1;
             }
    
    

    acquireSharedInterruptibly方法中,先调用了tryAcquireShared方法来判断state(在CountDownLatch中代表的是计数器的值)的值是否为0 ,不为0时, 调用doAcquireSharedInterruptibly方法阻塞线程;
    那么,doAcquireSharedInterruptibly是怎么实现的阻塞线程的呢?

        /**
         *  在共享可中断模式下获取。
         */
        private void doAcquireSharedInterruptibly(int arg)
            throws InterruptedException {
            final Node node = addWaiter(Node.SHARED);//1. 将该线程加入阻塞队列队尾
            boolean failed = true;
            try {
                for (;;) {
                    final Node p = node.predecessor();//获取前一个节点
                    if (p == head) {
                        int r = tryAcquireShared(arg);//2. 判断state是否为0; r>=0说明为0
                        if (r >= 0) {
                            //把当前节点设置成head节点,并传播 唤醒 所有被await()方法阻塞的节点
                            setHeadAndPropagate(node, r);
                            p.next = null; // help GC
                            failed = false;
                            return;
                        }
                    }
    
                    //2. 到此处,说明state != 0
                    //检查是否应该阻塞节点
                    if (shouldParkAfterFailedAcquire(p, node) &&
                            //阻塞节点
                        parkAndCheckInterrupt())
                        throw new InterruptedException();
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
    
        private Node addWaiter(Node mode) {
            //创建一个新的节点,封装有当前的线程实例
            Node node = new Node(Thread.currentThread(), mode);
            // Try the fast path of enq; backup to full enq on failure
            Node pred = tail;//队尾节点
            if (pred != null) {
                node.prev = pred;
                //采用CAS将当前节点设为队尾节点
                if (compareAndSetTail(pred, node)) {
                    pred.next = node;
                    return node;
                }
            }
            enq(node);//向队列队尾处插入节点,此处暂不赘述
            return node;
        }
        
        //挂起线程
        private final boolean parkAndCheckInterrupt() {
            LockSupport.park(this);
            return Thread.interrupted();
        }
    
    

    从代码中可以看出, AQS中有一个先进先出的队列.而在CountDownLatch类中, 该队列保存的就是被await()方法阻塞的线程. 在执行await()方法之前, 程序会先判断计数器的值是否为0,如果为0则直接执行该线程,反之会将该线程封装到Node节点中,并通过CAS操作将其保存到队列的队尾.然后阻塞该线程. 从这里你是不是猜到了, 既然将阻塞的线程都保存到队列中了,是不是就是为了在计数器值变为0时将其唤醒呢. 没错, 在接下来的countDown()方法中就能找到答案.

    countDown()方法:

        public void countDown() {
            sync.releaseShared(1);
        }
    
        public final boolean releaseShared(int arg) {
            if (tryReleaseShared(arg)) {//state(计数器值)减1,且当state为0时返回true
            	//唤醒线程
                doReleaseShared();
                return true;
            }
            return false;
        }
    		
            protected boolean tryReleaseShared(int releases) {
                // Decrement count; signal when transition to zero
                for (;;) {
                    int c = getState();
                    if (c == 0)
                        return false;
                    int nextc = c-1;
                    //CAS将计数器state的值减1
                    if (compareAndSetState(c, nextc))
                    //当state为0时返回true
                        return nextc == 0;
                }
            }
    

    可以看到,countDown()方法是利用CAS操作将计数器的值减1,减1成功之后,自然就是判断计数器值是否为0 ,为0时唤醒队列中阻塞的线程了. 那么我们接着看doReleaseShared()方法;

    doReleaseShared()

        private void doReleaseShared() {
            /*
             * 确保释放传播,即使有其他进行中的获取/释放。如果它需要信号,则以通常的方式尝试解除头的处理器。但如果不是,状态设置为PROPAGATE以确保在释放后,传播继续。
             * 另外,我们必须循环,以便在我们这样做的时候添加一个新的节点。此外,与unparkSuccessor的其他用法不同,我们需要知道CAS是否重置状态失败,如果这样重新检查。
             * 
             */
            for (;;) {
                Node h = head;
                if (h != null && h != tail) {
                    int ws = h.waitStatus;
                    if (ws == Node.SIGNAL) {
                        if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                            continue;            // loop to recheck cases
                        从头节点开始唤醒队列中的后续线程
                        unparkSuccessor(h);
                    }
                    else if (ws == 0 &&
                             !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                        continue;                // loop on failed CAS
                }
                if (h == head)                   // loop if head changed
                    break;
            }
        }
    

    唤醒队列中的线程:unparkSuccessor():

        private void unparkSuccessor(Node node) {
            //如果状态为负(即,可能需要信号)尝试在预期的信令中清除。如果这失败或者如果状态通过等待线程而改变,则是OK。
            int ws = node.waitStatus;
            if (ws < 0)
                compareAndSetWaitStatus(node, ws, 0);
    
            Node s = node.next;
            //如果下一个节点不存在或者已经取消等待,那么从尾节点向前遍历,找到离当前节点最近的而且在等待中的节点
            //疑问:为什么从队尾遍历不从当前节点开始遍历?
            //答:因为当前节点的下一个节点可能为空,往下遍历不了
            if (s == null || s.waitStatus > 0) {
                s = null;
                for (Node t = tail; t != null && t != node; t = t.prev)
                    if (t.waitStatus <= 0)
                        s = t;
            }
    
            //唤醒离当前节点最近的且在等待中的节点
            if (s != null)
                LockSupport.unpark(s.thread);
        }
    

    从代码中可以看到, 当计数器值为0 时,会根据队列中的头结点向队尾依次遍历获取阻塞中的节点并唤醒对应节点中的线程. 当下一个节点不存在或者已经取消等待时,会从队尾开始向头结点回溯遍历来唤醒对应的线程.

    展开全文
  • JS让代码中间间隔时间执行

    万次阅读 2016-10-20 17:05:41
    console.log("我执行了"); sleep(3000); console.log("我3000ms后执行了"); function sleep(numberMillis) { var now = new Date(); var exitTime = now.getTime() + numberMillis; while (true) {
    console.log("我执行了");
    sleep(3000);
    console.log("我3000ms后执行了");


     
    
    function sleep(numberMillis) {
        var now = new Date();
        var exitTime = now.getTime() + numberMillis;
        while (true) {
            now = new Date();
            if (now.getTime() > exitTime)
                return;
        }
    }

    展开全文
  • 【JS-task4】 return的用法是什么?若用在for循环中,还会执行下一次循环吗? 分享人:陈星宇 目录 1.背景介绍 2.知识剖析 3.常见问题 4.解决...
              【JS-task4】  
    
                return的用法是什么?若用在for循环中,还会执行下一次循环吗? 
                 分享人:陈星宇
             
             
                 目录 
                 1.背景介绍 
                 2.知识剖析 
                 3.常见问题 
                 4.解决方案 
                 5.编码实战 
                 6.扩展思考 
                 7.参考文献 
                 8.更多讨论 
             
             
    一.背景介绍 
             
             
                 什么是return? 
                 
                     return 语句会终止函数的执行,并返回函数的值。 
                语法:
                    return value;
                可选项 value指定返回的值。如果忽略则返回undefined.
               

                在函数中 ,return 语句用于终止一个函数的执行,并返回值value。

                如果value被省略或在函数内没有 return 语句被执行,则函数返回undefined。 

                 


             
             
    二.知识剖析 
             
             
                 return语句的用法 
     
                 1、中止函数的执行,并返回函数执行的结果</h4>
                 语法为:return+表达式 
                  return 返回的值可以是任何数据类型 
               
       function type(){
                       var a=1;
                       var b=2;
                       return a+b;    //返回数值
                       alert('a')
                      }
                    type();

                    console.log(type());


                    function string(){
                       return "字符串"   //返回字符串
                    }

                    console.log(string());


                    function arr(){
                      return [1,2,3,4]      //返回数组
                    }

                    console.log(arr());


                    function object(){
                    return {"name":"cxx", "age":13}  //返回对象
                    }
                    console.log(object());
                
             
                 2、使用return阻止某些浏览器默认的行为
                 语法为:return false; 
                 可以在a标签中实践一下。 
                 请看demo的例子: 
                              
                         <span class="ojbk">
                             <a id="btn1" href="https://www.baidu.com/">按钮1</a>
                             <a id="btn2" href="https://www.baidu.com/">按钮2</a>
                         </span>
                         <script>
                             $('#btn1').on('click',function () {//点击按钮1要发生的事
                                 alert("按钮1测试弹窗(默认情况会跳转)");
                                 return true;
                             });
                             $('#btn2').on('click',function () {//点击按钮2要发生的事
                                 alert("按钮2测试弹窗(return false阻止默认跳转)");
                                 return false;
                             });
                         </script>


             
    三.常见问题  
                       

                     1.若return用在for循环中,还会执行下一次循环吗? 

                     2.除了return之外,还有哪些语句可以跳出循环? 

                     3.多层for循环return会跳出一层还是直接跳出                

                     4.return和break和continue区别

    四. 解决方案  
             
             回答问题1:
                 代码示例: 
            
                    function jumpLoop() {
                       result = []
                       for(var i=0;i<10;i++){
                          result.push(i)
                          if(i===8){
                             return result;
                          }
                       }
                    }
                    console.log(jumpLoop())
               
                  我们可以看到,for循环只返回return所返回的值,并不会执行下一次循环。 
             
             
                回答问题2: 除了return之外,还有哪些语句可以跳出循环?
                 
                     (1)break 
                   
                        for(var i=0;i<=10;i++){
                           console.log(i);
                           if(i==5){break;}
                        }
                    
                     上面这个break实例,输出的结果为:12345,当i的值等于5的时候直接通过break跳出了循环,不再继续往下运行。 
                           
                     (2)continue 
                   
                            for(var i=1;i<=10;i++){
                                if (i === 3||i===7) continue;
                                console.log(i);
                            }
                       

                     上面这个continue实例,输出的结果为:124568910,当i的值等于3或者7的时候直接跳过,继续执行循环。 

         

      回答问题3       

                   多层for循环中,return如果跳出循环,只会跳出它所在的那一层循环,并不影响其他层的循环。 

      回答问题4  

                    break 跳出总上一层循环,不再执行循环(结束当前的循环体)
                    continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件) 
                    return 程序返回,不再执行下面的代码(结束当前的方法 直接返回) 

             
    五.编码实战  
                             
    六.扩展思考 
                     jq的return false 和原生的return false有什么区别 
                 
                 
                    1.在jq中使用return false实际上它完成了3件事:
                        1.event.preventDefault()

                        preventDefault() 方法阻止元素发生默认的行为 

                        2.event.stopPropagation()

                        event.stopPropagation()阻止捕获和冒泡阶段中当前事件的进一步传播 

                        3.终止函数的执行并返回结果。
                        jq的return false会同时阻止浏览器默认事件的发生,阻止事件的冒泡,并且返回函数值,而在原生js中,return并                      不能阻止事件的冒泡.
                     
                 
                 
                    2.JS中return False 就相当于终止符,终止默认的事件行为
                 
             
     七.参考文献 
                   参考1:event.preventDefault() vs. return false
                   参考2:javascript中break,continue和return语句用法小结
                   参考3: js中return的用法
    展开全文
  • 首先这里有个结论:想要解决这个问题,我们只能选择监听animationend事件,其他的我们以为的可以解决的方案都是不可行的。 1、页面中的元素 &amp;lt;div class=&quot;st_apples&quot;&amp;gt; &...

    首先这里有一个结论:想要解决这个问题,我们只能选择监听animationend事件,其他的我们以为的可以解决的方案都是不可行的。

    1、页面中的元素

    <div class="st_apples">
    	<!-- 动画会作用在这个span上 -->
    	<span data-value=""></span>
    </div>
    

    2、CSS样式

    .st_apples .apple_select {
                -webkit-animation: changeBg 3s linear;
                animation: changeBg 3s linear;
            }
            @-webkit-keyframes changeBg {
                0% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    -webkit-transform: scale(1);
                }
                25% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    -webkit-transform: scale(2);
                }
                50% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    -webkit-transform: scale(1);
                }
                75% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    -webkit-transform: scale(2);
                }
                100% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    -webkit-transform: scale(1);
                }
            }
    
            @keyframes changeBg {
                0% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    transform: scale(1);
                }
                25% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    transform: scale(2);
                }
                50% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    transform: scale(1);
                }
                75% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    transform: scale(2);
                }
                100% {
                    background: url("${ctx}/style/images/sharedServices/new/apple_big.png") no-repeat;
                    background-size: 100% 100%;
                    transform: scale(1);
                }
            }
    

    这个动画是什么效果就不做介绍了。

    之前的JQuery操作方式

    $(".st_apples span[data-value="").addClass("apple_select").siblings().removeClass("apple_select");
    

    这里想要实现的逻辑就是遍历一个数据,然后去找对应的span标签,让它闪烁。
    所以就出现问题了,如果有连续两条数据对应的span是一样的,那么这个动画就一共只会执行一次。
    我开始也以为不断的给它设置class就没问题,但是事与愿违。

    解决方式

    在此之前,需要了解 存在“动画结束”这个事件,各个版本的浏览器监听的不同:

    var animations = {
         "animation": "animationend",
         "OAnimation": "oAnimationEnd",
         "MozAnimation": "animationend",
         "WebkitAnimation": "webkitAnimationEnd"
     }
    

    具体都是对应的什么浏览器大家自己去了解一下。
    所以给每一个span绑定监听事件就可以了:

    $(".st_apples span").each(function() {
         // 目前只设置兼容谷歌浏览器
         $(this)[0].addEventListener("webkitAnimationEnd",function(){
         	 // 动画结束就直接去除这个动画
             $(this).css("animation","");
         });
     });
    

    然后记得将上面的添加删除class的操作直接改为添加删除animation:

    $(".st_apples span[data-value="+remark+"]").css("animation","changeBg 3s linear");
    

    ok,到此为止,喔,对了,提醒一件小事情,因为动画结束到监听事件的内部代码(去除动画)执行完成存在一定的延迟。所以如果你的代码中存在定时器,那么请将定时器的时间稍微设置的比动画时间大一点,我一般设置1秒。这一点要切记。

    展开全文
  • 这是我的第78篇原创文章。作者 | 王磊来源 | Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG_Stone)我们在日常开发中经常需要测试一些代码的执行时...
  • http://blog.csdn.net/hu_songsong/article/details/12845391 ... 如何创建一个线程,要求可以一直工作,不会执行一次就结束。 @synthesize
  • Java统计代码的执行时间的6种方法

    千次阅读 2020-09-23 09:40:53
    在日常开发中经常需要测试一些代码的执行时间,但又不想使用向 JMH(Java Microbenchmark Harness,Java 微基准测试套件)这么重的测试框架,所以本文就汇总了一些 Java 中比较常用的执行时间统计方法,总共包含以下...
  • python结束语句

    千次阅读 2020-11-29 14:45:01
    广告关闭腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元!... (2) 冒号(:)出现在结尾,表示个语句的结束。 (3) 分号(;)不用出现在结尾。 (4) 大括号不在...
  • 如何结束C ++代码

    千次阅读 2021-05-19 14:39:28
    RAII和堆栈展开C ++使用了个名为RAII的习语,简单来说就是对象应该在构造函数中执行初始化并在析构函数中进行清理。例如,std::ofstream类[可]在构造函数中打开文件,然后用户对其执行输出操作,最后在其生命周期...
  • 我有个类,计划这个Runnable执行使用个ScheduledExecutorService与scheduleWithFixedDelay。目标我想改变这个类来调度Runnable的固定延迟执行无限期,或者直到它已经运行了一定次数,这取决于传递给构造函数的...
  • 大家都知道Android涉及到与UI相关的操作只能在主线程执行 android4.0以后就禁止在主线程进行网络请求了,在主线程里面执行Http请求都会报NetworkOnMainThreadException的异常. 于是乎,我们现在用的Volley,Android-...
  • vue-router 多个路由地址绑定个组件造成 created 不执行的解决方法需求分析导航上有2个菜单,指向的是同个列表,但是是不同的状态。我需要根据不同的状态获取状态参数给接口拿到不同的数据。需求貌似很简单 *0_0...
  • 符号执行技术总结(A Brief Summary of Symbol Execution)Prologue摘要简介经典符号执行技术现代符号执行技术混合执行测试(Concolic testing)执行生成测试(Execution-Generated Testing (EGT))动态符号执行中的...
  • CPU内部组成结构及指令执行过程

    万次阅读 多人点赞 2015-05-15 09:53:16
    计算机的基本硬件系统由运算器、控制器、存储器和输入、... CPU通过执行指令来控制程序的执行顺序,这是CPU的重要职能。  (2)操作控制  条指令功能的实现需要若干个操作信号来完成,CPU产生每条指令的操作信号并
  • JS中的事件循环原理以及异步执行过程这些知识点对新手来说可能有点难,但是是必须迈过的坎,逃避是解决不了问题的,本篇文章旨在帮你彻底搞懂它们。 说明:本篇文章主要是考虑浏览器环境,Node环境我没有研究过暂时...
  • 现在工作几年后发现,很多以前看过、用过的东西,再次拿起的时候总觉得记不牢靠。"好记性不如烂笔头"应该是某位上了年纪的大叔的切肤之痛(仅次于上了年纪的难言之瘾)。 我觉得这事得怪怪中国
  • JavaScript宏任务(macrotask)和 微任务(microtask) 执行顺序

    千次阅读 多人点赞 2021-06-14 17:53:39
    JavaScript是单线程指的是同一时间只能干一件事情,只有前面的事情执行完,才能执行后面的事情。导致遇到耗时的任务时后面的代码无法执行。 在此之前啊 我们必须了解同步和异步 1. 同步任务(synchronous) ...
  • SQL语句执行过程详解

    万次阅读 2017-04-15 09:30:58
    条sql,plsql的执行到底是怎样执行的呢? 、SQL语句执行原理: 第步:客户端把语句发给服务器端执行 当我们在客户端执行 select 语句时,客户端会把这条 SQL 语句发送给服务器端,让服务器端的 进程来处理这...
  • 前言: 有的人走一步,看一步,学一点,算一点,缺少知识的系统化观念; 有的人今天学点,明天学点,后天学点,缺少...题目:学习从来不是一件轻松的事情,但也从来不是一件艰难的事情 之所以忽然提笔,是因为这段
  • JS页面加载完毕后执行的多种方式和比较

    万次阅读 多人点赞 2019-07-31 18:40:41
    做项目的时候可能会遇到这种情况: 个页面的中定义了多个onload事件,那么在此定义window.onload函数的时候可能会不生效或者多个onload之间覆盖的现象. 有的朋友肯定会说用jQuery的$(document).ready(function(){}...
  • 在JS执行中都是单线程执行,所以代码的执行可以说是自上而下,如果前段的代码出现问题,就会导致下一段代码无法执行,对于用户而言就是卡死现象,所以在JS执行机制引出了异步执行操作。 那异步能解决...
  • 之前在阅读《Javascript高级程序设计》「4.2执行环境及作用域的」时候,对相关的概念理解得并不是非常的透彻,只是懂了大概的意思。后来在看到「闭包」这一节时书中再一次提到了相关的概念,并且这些是充分理解闭包...
  • 在JS执行中都是单线程执行,所以代码的执行可以说是自上而下,如果前段的代码出现问题,就会导致下一段代码无法执行,对于用户而言就是卡死现象,所以在JS执行机制引出了异步执行操作。 那异步能解决什么呢问题,...
  • 疯狂Activiti6.0连载(25)BPMN结束事件

    千次阅读 2017-12-10 20:24:17
    Activiti BPMN 结束事件
  • Animation动画概述和执行原理

    千次阅读 2018-12-27 16:49:02
    start()函数当getTransformation()第次被调用的时候开始执行。 startNow()动画被立即执行 start和startNow内部都是调用setStartTime函数,setStartTime函数是设置动画开始执行时间。start函数设置...
  • Python continue继续循环用法总结

    千次阅读 2020-11-26 01:25:17
    执行到return语句时,会退出函数,return之后的语句不再执行。 但将return语句放在try语句块中,是个例外,finally语句块中的语句依然会执行 。 举例: 正常函数:执行到该return语句时,函数终止,后边的语句不再...
  • 重复执行——循环结构

    千次阅读 2019-12-02 22:57:02
    先计算表达式的值,当表达式值为真时,执行一次循环体。也就是“当表达式成立时,不断重复执行循环体”,所以又称为“当型循环”。 2、do—while语句 此语句是C++中用于解决至少执行一次重复操作(循环体)的循环...
  • Java程序运行时,第一件事情就是试图访问main方法,因为main相等于程序的入口,如果没有main方法,程序将无法启动,main方法更是占一个独立的线程,找到main方法后,是不是就会执行mian方法块里的第一句话呢?...
  • 教你怎么查看 hive 的执行计划

    千次阅读 多人点赞 2020-03-06 16:21:37
    我们在总结Hive架构的时候,我们知道Hive中有个Compiler组件,这个组件主要是解析字符串的SQL,然后生成执行计划,我们介绍文章主要是详细讲解Compiler中的细节以及生成的执行计划 我们从下面的HiveSQL语句开始: ...
  • JavaScript的执行原理

    万次阅读 多人点赞 2017-06-05 17:22:59
    JavaScript运行原理 单线程 JS引擎 执行栈 任务队列 同步、异步

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 223,178
精华内容 89,271
关键字:

时间结束再执行下一件