精华内容
下载资源
问答
  • /// 任务队列 /// </summary> public class TaskQueue { #region 构造函数 /// <summary> /// 默认队列 /// 注:默认间隔时间1ms /// </summary> public TaskQueue() { _timeSpan = ...
  • 事件循环与任务队列 是JS中比较重要的两个概念,在ES6中,清楚的区分宏观任务和微观任务队列才能解释Promise的一些表现。 js是单线程语言,对于异步操作只能先把它放在一边,按照某种规则按先后顺序放进一个容器...

    相信你看到这篇博客,应该也想更多更深入的了解下:

    事件循环与任务队列 是JS中比较重要的两个概念,在ES6中,清楚的区分宏观任务和微观任务队列才能解释Promise的一些表现。

     

    js是单线程语言,对于异步操作只能先把它放在一边,按照某种规则按先后顺序放进一个容器(其实就是存入宏观任务和微观任务队列中),先处理同步任务,再处理异步任务。异步任务分为 [ 宏观任务队列、微观任务队列 ]

    按照规定,能发起宏观任务的方法有:

    script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境);

    微观任务的方法有:

    Promise.then、MutaionObserver、process.nextTick(Node.js 环境),async/await实际上是promise+generator的语法糖,也就是promise,也就是微观任务;
     

    同步任务结束后,先处理微观任务后处理宏观任务 

    先来看一段代码:

    // 先来看下下面这段代码
    async function async1() {
      console.log('async1 start');
      await async2();
      console.log('async1 end');
    }
    async function async2() {
      console.log('async2');
    }
    
    console.log('script start');
    
    setTimeout(function() {
      console.log('setTimeout');
    }, 0)
    
    async1();
    
    new Promise(function(resolve) {
      console.log('promise1');
      resolve();
    }).then(function() {
      console.log('promise2');
    });
    console.log('script end');
    
    
    /*执行结果
    script start
    async1 start
    async2
    promise1
    script end
    async1 end
    promise2
    setTimeout
    */

    先大体看下代码:

    从上往下看,先走同步队列,再走异步队列(包含微观任务队列和宏观任务队列)。

    同步队列:script start → async1 start → async2 → promise1 → script end

    异步队列:包括微观任务和宏观任务。

    微观任务:async1 end → promise2

    宏观任务: setTimeout →

    大概思路描述如下:

     

    --------end。 

    展开全文
  • iocp 任务队列

    2015-12-28 01:13:51
    想着自己实现一个无锁的任务队列, 后来考虑IOCP就是一个队列,其分发效率应该高的非常可以吧, 于是自己用iocp封装了一个任务队列 ,实际测试debug版本每秒50w条, release每秒100w条
  • 使用redis做任务队列分发子任务,用于分布式拆分子任务提高系统运行效率
  • 1. 事件轮询(Event Loop) js实现异步的具体解决方案 ...EXP4:微任务队列中创建的宏任务 总结 这篇博文仅为个人理解,文章内提供一些更加权威的参考,如有片面及错误,欢迎指正 1. 事件轮询...
     
    

    这篇博文仅为个人理解,文章内提供一些更加权威的参考,如有片面及错误,欢迎指正

    1. 事件轮询(Event Loop)

    什么是 Event Loop? - 阮一峰

    事件轮询(Event Loop) - 《你不懂JS:异步与性能》

    【推荐】详解JavaScript中的Event Loop(事件循环)机制

    Javascript的宿主环境中共通的一个“线程”(一个“不那么微妙”的异步玩笑,不管怎样)是,他们都有一种机制:在每次调用JS引擎时,可以随着时间的推移执行你的程序的多个代码块儿,这称为“事件轮询(Event Loop)”。

    换句话说,JS引擎对 时间 没有天生的感觉,反而是一个任意JS代码段的按需执行环境。是它周围的环境在不停地安排“事件”(JS代码的执行)。

    js实现异步的具体解决方案

    • 同步代码直接执行
    • 异步函数到了指定时间再放到异步队列
    • 同步执行完毕,异步队列轮询执行。

    什么叫轮询?

    精简版:当第一个异步函数执行完之后,再到异步队列监视。一直不断循环往复,所以叫事件轮询。

    详细版:js引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js会将这个事件加入与当前执行栈不同的另一个队列,我们称之为事件队列。被放入事件队列不会立刻执行其回调,而是等待当前执行栈中的所有任务都执行完毕, 主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码…,如此反复,这样就形成了一个无限的循环。这就是这个过程被称为“事件循环(Event Loop)”的原因。

    事实上,事件轮询与宏任务和微任务密切相关。

    2. 宏任务和微任务

    概念

    微任务、宏任务与Event-Loop

    在一个事件循环中,异步事件返回结果后会被放到一个任务队列中。然而,根据这个异步事件的类型,这个事件实际上会被对应的宏任务队列或者微任务队列中去。并且在当前执行栈为空的时候,主线程会 查看微任务队列是否有事件存在。如果不存在,那么再去宏任务队列中取出一个事件并把对应的回到加入当前执行栈;如果存在,则会依次执行队列中事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的一个事件,把对应的回调加入当前执行栈…如此反复,进入循环。

    我们只需记住当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。

    在当前的微任务没有执行完成时,是不会执行下一个宏任务的。
    所以就有了那个经常在面试题、各种博客中的代码片段:

    setTimeout(_ => console.log(4))
    
    new Promise(resolve => {
      resolve()
      console.log(1)
    }).then(_ => {
      console.log(3)
    })
    
    console.log(2)
    

    setTimeout就是作为宏任务来存在的,而Promise.then则是具有代表性的微任务,上述代码的执行顺序就是按照序号来输出的。
    所有会进入的异步都是指的事件回调中的那部分代码
    也就是说new Promise在实例化的过程中所执行的代码都是同步进行的,而then中注册的回调才是异步执行的。
    在同步代码执行完成后才回去检查是否有异步任务完成,并执行对应的回调,而微任务又会在宏任务之前执行。
    所以就得到了上述的输出结论1、2、3、4。

    +部分表示同步执行的代码

    +setTimeout(_ => {
    -  console.log(4)
    +})
    
    +new Promise(resolve => {
    +  resolve()
    +  console.log(1)
    +}).then(_ => {
    -  console.log(3)
    +})
    
    +console.log(2)
    

    本来setTimeout已经先设置了定时器(相当于取号),然后在当前进程中又添加了一些Promise的处理(临时添加业务)。

    所以进阶的,即便我们继续在Promise中实例化Promise,其输出依然会早于setTimeout的宏任务:如EXP2

    宏任务

    分类:

    #浏览器Node
    I/O
    setTimeout
    setInterval
    setImmediate
    requestAnimationFrame

    特性:

    1. 宏任务所处的队列就是宏任务队列

    2. 第一个宏任务队列中只有一个任务:执行主线程上的JS代码;如果遇到上方表格中的异步任务,会创建出一个新的宏任务队列,存放这些异步函数执行完成后的回调函数。

    3. 宏任务队列可以有多个

    4. 宏任务中可以创建微任务,且如果该微任务立即被加入执行栈的话,会打断当前宏任务的执行。(EXP3)

    5. 当一个宏任务队列中的任务全部执行完后,会查看是否有微任务队列,如果有就会优先执行微任务队列中的所有任务,如果没有就查看是否有宏任务队列

    微任务

    分类:

    #浏览器Node
    process.nextTick
    MutationObserver
    Promise.then catch finally

    特性:

    1. 微任务所处的队列就是微任务队列

    2. 在上一个宏任务队列执行完毕后,如果有微任务队列就会执行微任务队列中的所有任务

    3. new promise((resolve)=>{ 这里的函数在当前队列直接执行 }).then( 这里的函数放在微任务队列中执行 )

    4. 微任务队列上创建的微任务,仍会阻碍后方将要执行的宏任务队列 (EXP2)

    5. 由微任务创建的宏任务,会被丢在异步宏任务队列中执行 (EXP4)

    例题

    EXP1: 在主线程上添加宏任务与微任务

    执行顺序:主线程 => 主线程上创建的微任务 => 主线程上创建的宏任务

    console.log('-------start--------');
    
    setTimeout(() => {
      console.log('setTimeout');  // 将回调代码放入另一个宏任务队列
    }, 0);
    
    new Promise((resolve, reject) => {
      for (let i = 0; i < 5; i++) {
        console.log(i);
      }
      resolve()
    }).then(()=>{
      console.log('Promise实例成功回调执行'); // 将回调代码放入微任务队列
    })
    
    console.log('-------end--------');
    

    结果:

    -------start--------
    0
    1
    2
    3
    4
    -------end--------
    Promise实例成功回调执行
    setTimeout
    

    由EXP1,我们可以看出,当JS执行完主线程上的代码,会去检查在主线程上创建的微任务队列,执行完微任务队列之后才会执行宏任务队列上的代码

    EXP2: 在微任务中创建微任务

    执行顺序:主线程 => 主线程上创建的微任务1 => 微任务1上创建的微任务2 => 主线程上创建的宏任务

    setTimeout(_ => console.log(4))
    
    new Promise(resolve => {
      resolve()
      console.log(1)
    }).then(_ => {
      console.log(3)
      Promise.resolve().then(_ => {
        console.log('before timeout')
      }).then(_ => {
        Promise.resolve().then(_ => {
          console.log('also before timeout')
        })
      })
    })
    
    console.log(2)
    

    结果:

    1
    2
    3
    before timeout
    also before timeout
    4
    

    由EXP1,我们可以看出,在微任务队列执行时创建的微任务,还是会排在主线程上创建出的宏任务之前执行

    EXP3: 宏任务中创建微任务

    宏任务队列中创建的微任务,会打断当前宏任务队列的执行。

    执行顺序:主线程(宏任务队列 1)=> 宏任务队列 2.1 => 微任务队列 1(打断宏任务队列 2)=>宏任务队列 2.2 => 宏任务队列 3

    // 宏任务队列 1
    setTimeout(() => {
      // 宏任务队列 2.1
      console.log('timer_1');
      setTimeout(() => {
        // 宏任务队列 3
        console.log('timer_3')
      }, 0)
      new Promise(resolve => {
        resolve()
        console.log('new promise')
      }).then(() => {
        // 微任务队列 1
        console.log('promise then')
      })
    }, 0)
    
    setTimeout(() => {
      // 宏任务队列 2.2
      console.log('timer_2')
    }, 0)
    
    console.log('========== Sync queue ==========')
    

    结果:

    ========== Sync queue ==========
    timer_1
    new promise
    promise then
    timer_2
    timer_3
    

    EXP4:微任务队列中创建的宏任务

    执行顺序:主线程 => 主线程上创建的微任务 => 主线程上创建的宏任务 => 微任务中创建的宏任务

    异步宏任务队列只有一个,当在微任务中创建一个宏任务之后,他会被追加到异步宏任务队列上(跟主线程创建的异步宏任务队列是同一个队列)

    // 宏任务1
    new Promise((resolve) => {
      console.log('new Promise(macro task 1)');
      resolve();
    }).then(() => {
      // 微任务1
      console.log('micro task 1');
      setTimeout(() => {
        // 宏任务3
        console.log('macro task 3');
      }, 0)
    })
    
    setTimeout(() => {
      // 宏任务2
      console.log('macro task 2');
    }, 1000)
    
    console.log('========== Sync queue(macro task 1) ==========');
    

    结果:

    ========== Sync queue(macro task 1) ==========
    micro task 1
    macro task 3
    macro task 2
    

    总结

    微任务队列优先于宏任务队列执行,微任务队列上创建的宏任务会被后添加到当前宏任务队列的尾端,微任务队列中创建的微任务会被添加到微任务队列的尾端。只要微任务队列中还有任务,宏任务队列就只会等待微任务队列执行完毕后再执行。

    最后上一张几乎涵盖基本情况的例图和例子

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E9JbttZi-1622687528232)(https://ws1.sinaimg.cn/large/a71efaafly1g232hxfbhrj21350h9406.jpg)]

    console.log('======== main task start ========');
    new Promise(resolve => {
      console.log('create micro task 1');
      resolve();
    }).then(() => {
      console.log('micro task 1 callback');
      setTimeout(() => {
        console.log('macro task 3 callback');
      }, 0);
    })
    
    console.log('create macro task 2');
    setTimeout(() => {
      console.log('macro task 2 callback');
      new Promise(resolve => {
        console.log('create micro task 3');
        resolve();
      }).then(() => {
        console.log('micro task 3 callback');
      })
      console.log('create macro task 4');
      setTimeout(() => {
        console.log('macro task 4 callback');
      }, 0);
    }, 0);
    
    new Promise(resolve => {
      console.log('create micro task 2');
      resolve();
    }).then(() => {
      console.log('micro task 2 callback');
    })
    
    console.log('======== main task end ========');
    

    结果:

    ======== main task start ========
    create micro task 1
    create macro task 2
    create micro task 2
    ======== main task end ========
    micro task 1 callback
    micro task 2 callback
    macro task 2 callback
    create micro task 3
    create macro task 4
    micro task 3 callback
    macro task 3 callback
    macro task 4 callback
    
    展开全文
  • 事件循环 JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应用而生。...任务队列
    事件循环

    JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应用而生。Event Loop 包含两类:一类是基于 Browsing Context,一种是基于 Worker。二者的运行是独立的,也就是说,每一个 JavaScript 运行的"线程环境"都有一个独立的 Event Loop,每一个 Web Worker 也有一个独立的 Event Loop。

    任务队列

    vue 数据驱动视图是数据改变,视图异步等待所有数据变化完成,统一进行视图更新。

    既然是异步就有顺序和优先级, 异步任务队列是那种顺序执行 ?

    tip: 微任务优先级高于宏任务 MDN 介绍

    任务队列主要分为两种:

    1、microtasks(微任务):

    • Promise :ES6的异步处理方案
    • process.nextTick(vue.nextTick) :下轮tick更新机制,
    • Mutation Observer API: DOM改变 监听 API

    2、macrotasks(宏任务也称任务):

    • setTimeout() : 延时器

    • setInterval(): 计时器

    • setImmediate:node.js 回调函数延迟执行,process.nextTicl() 方法十分类似

      process.nextTick()中的回调函数执行的优先级要高于setImmediate().这里的原因在于事件循环对观察者的检查是有先后顺序的,process.nextTick()属于idle观察者,setImmediate()属于check观察者。在每一个轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者。

      在具体实现上,process.nextTick()的回调函数保存在一个数组中,setImmediate()的结果则是保存在链表中。在行为上,process.nextTick()在每轮循环中会将该数组中的回调函数全部执行完,而setImmediate()在每轮循环中执行链表中的一个回调函数

    • I/O :系统IO(input/output)

    • UI render :页面渲染

    • requestAnimationFrame():异步动画渲染 ,浏览器调用指定的函数以在下次重绘之前更新动画

    如何理解微任务和宏任务?

    创造代码的人也是人,他们的灵感多数来自于生活。我们这里打个比方(朴灵老师也这样比喻),javascript处理异步就像去餐馆吃饭,服务员会先为顾客下单,下完单把顾客点的单子给后厨让其准备,然后就去服务下一位顾客,,而不是一直等待在出餐口。
    javascript将顾客下单的行为进行了细分。无外乎两种酒水类和非酒水类。对应着我们javascript中的macroTask和microTask。

    但是在不同场景下的步骤是不一样的,就像西餐和中餐。西餐划分的非常详细:头盘->汤->副菜->主菜->蔬菜类菜肴->甜品->咖啡,中餐就相对简单许多:凉菜->热菜->汤。

    任务队列,下面看几个示例, 输出内容便是执行顺序:

    setTimeout(()=>{
        console.log('1')
    
        Promise.resolve().then(function() {
            console.log('2')
        })
    }, 0)
    
    setTimeout(()=>{
        console.log('3')
    
        Promise.resolve().then(function() {
            console.log('4')
        })
    }, 0)
    
    setTimeout(function() {console.log('6')}, 0)
    
    requestAnimationFrame(function(){
        console.log('5')
    })
    
    setTimeout(function() {console.log('7')}, 0)
    
    new Promise(function executor(resolve) {
        console.log('1')
        resolve()
        console.log('2')
    }).then(function() {
        console.log('4')
    })
    
    console.log('3')
    
    console.log('1');
    
    setTimeout(() => {
        console.log('5');
        process.nextTick(() => console.log('6'));
    }, 0);
    
    process.nextTick(() => {
        console.log('3');
        process.nextTick(() => console.log('4'));
    });
    
    console.log('2');
    

    这样就可以理解Vue的异步更新策略运行机制

      created() {
        this.textDemo()
      },
      methods: {
        textDemo() {
          console.log(1)
    
          setTimeout(() => { // macroTask
            console.log(4)
    
            setTimeout(() => { // macroTask
              console.log(8)
            }, 0)
    
            this.$nextTick(() => { // microTask
              console.log(5)
            })
    
            Promise.resolve().then(function() { // microTask
              console.log(7)
            })
    
            this.$nextTick(() => { // microTask
              console.log(6)
            })
          }, 0)
    
          this.$nextTick(() => { // microTask
            console.log(3)
          })
    
          console.log(2)
        },
    }
    

    到此我们已经知道代码是如何运行的了, 如果你想要更深入理解, 请继续向下阅读。

    深究Vue异步更新策略原理

    我们先看一个示例:

    <template>
      <div>
        <div ref="test">{{test}}</div>
        <button @click="handleClick">tet</button>
      </div>
    </template>
    <script>
    export default {
        data () {
            return {
                test: 'begin'
            };
        },
        methods () {
            handleClick () {
                this.test = 'end';
                console.log(this.$refs.test.innerText);// 结果输出 begin
            }
        }
    }
    </script>
    

    通过上面示例可以看出 Vue是异步执行DOM更新, 更新会缓冲到队列中, 在nextTick 集中刷新队列并执行实际 (已去重的) 工作

    当然新版 this.$nextTick 有一些变化 。从Vue 2.5+开始,抽出来了一个单独的文件next-tick.js来执行它。
    在这里插入图片描述

    其大概的意思就是:在Vue 2.4之前的版本中,nextTick 几乎都是基于 microTask 实现的(具体可以看文章nextTick一节),但是由于 microTask 的执行优先级非常高,在某些场景之下它甚至要比事件冒泡还要快,就会导致一些诡异的问题;但是如果全部都改成 macroTask,对一些有重绘和动画的场景也会有性能的影响。所以最终 nextTick 采取的策略是默认走 microTask,对于一些DOM的交互事件,如 v-on绑定的事件回调处理函数的处理,会强制走 macroTask。

    具体做法就是,在Vue执行绑定的DOM事件时,默认会给回调的handler函数调用withMacroTask方法做一层包装,它保证整个回调函数的执行过程中,遇到数据状态的改变,这些改变而导致的视图更新(DOM更新)的任务都会被推到macroTask。

    源码:

    function add$1 (event, handler, once$$1, capture, passive) {
        handler = withMacroTask(handler);
        if (once$$1) { handler = createOnceHandler(handler, event, capture); }
        target$1.addEventListener(
            event,
            handler,
            supportsPassive
            ? { capture: capture, passive: passive }
            : capture
        );
    }
    
    /**
     * Wrap a function so that if any code inside triggers state change,
     * the changes are queued using a Task instead of a MicroTask.
     */
    function withMacroTask (fn) {
        return fn._withTask || (fn._withTask = function () {
            useMacroTask = true;
            var res = fn.apply(null, arguments);
            useMacroTask = false;
            return res
        })
    }
    

    最后,写一段DEMO验证一下 :

    <template>
    	<div>
    	    <button @click="handleClick">change</button>
    	</div>
    </template>
    <script>
    export default {
       created() {
          this.handleClick() //  得出结果 : 2 3 1 4
      },
       methods: {
    	   handleClick() {
    	     setTimeout(() => { // macroTask
    	       console.log(4)
    	     }, 0)
    	
    	     this.$nextTick(() => { // microTask
    	       console.log(2)
    	     })
    	
    	     Promise.resolve().then(function() { // microTask
    	       console.log(1)
    	     })
    	
    	     this.$nextTick(() => { // microTask
    	       console.log(3)
    	     })
    	   }
       }
    }
    </script>
    

    在Vue 2.5+中,这段代码的输出顺序是1 - 2 - 3 - 4, 而 Vue 2.4 和 不通过DOM 输出 2 - 3 - 1 - 4。nextTick执行顺序的差异正好说明了上面的改变。

    tips: 所以这里需要留意遇到DOM操作, 同步执行受阻或者节点内容未及时更新可以使用 this.$nextTick 等待一下在执行下面的操作。

    <div id="example">
        <audio ref="audio"
               :src="url"></audio>
        <span ref="url"></span>
        <button @click="changeUrl">click me</button>
    </div>
    <script>
    const musicList = [
        'http://sc1.111ttt.cn:8282/2017/1/11m/11/304112003137.m4a?tflag=1519095601&pin=6cd414115fdb9a950d827487b16b5f97#.mp3',
        'http://sc1.111ttt.cn:8282/2017/1/11m/11/304112002493.m4a?tflag=1519095601&pin=6cd414115fdb9a950d827487b16b5f97#.mp3',
        'http://sc1.111ttt.cn:8282/2017/1/11m/11/304112004168.m4a?tflag=1519095601&pin=6cd414115fdb9a950d827487b16b5f97#.mp3'
    ];
    var vm = new Vue({
        el: '#example',
        data: {
            index: 0,
            url: ''
        },
        methods: {
            changeUrl() {
                this.index = (this.index + 1) % musicList.length
                this.url = musicList[this.index];
                this.$refs.audio.play();
            }
        }
    });
    </script>
    

    毫无悬念,这样肯定是会报错的:

    Uncaught (in promise) DOMException: The element has no supported sources.
    

    原因就在于audio.play()是同步的,而这个时候DOM更新是异步的,src属性还没有被更新,结果播放的时候src属性为空,就报错了。

    解决办法就是在play的操作加上this.$nextTick()

    this.$nextTick(function() {
        this.$refs.audio.play();
    });
    
    异步更新有什么好处?
    <template>
      <div>
        <div>{{test}}</div>
      </div>
    </template>
    <script>
    export default {
        data () {
            return {
                test: 0
            };
        },
        mounted () {
          for(let i = 0; i < 1000; i++) {
            this.test++;
          }
        }
    }
    </script>
    

    上面的例子非常直观, 可以这么理解当数据更新同步操作DOM会出现频繁渲染视图造成页面卡顿,极端的消耗资源。所以异步更新大大提升了性能, 并且数据更新很高效体验并没有降低

    展开全文
  • 分布式 Swift 任务队列。.zip,分布式任务队列
  • C#任务队列的实现

    热门讨论 2012-10-30 10:42:59
    用C#实现任务队列,一个队列存放任务,线程互斥的从任务队列中取,放任务,任务队列为空,线程等待,直到有任务加入队列为止。
  • Redis应用之任务队列

    千次阅读 2019-03-17 13:54:35
    Redis实现任务队列 1.任务队列 松耦合性   生产者和消费者无需知道彼此的实现细节,只需要约定好任务的描述格式,这使得生产者和消费者可以由不同的团队使用不同的编程语言编写。 易于扩展   消费者可以有多个,...

    Redis实现任务队列

    1.任务队列

    松耦合性

      生产者和消费者无需知道彼此的实现细节,只需要约定好任务的描述格式,这使得生产者和消费者可以由不同的团队使用不同的编程语言编写。

    易于扩展

      消费者可以有多个,而且可以分布在不同的服务器中,如下图,借此可以轻易的降低单台服务器的负载。
    在这里插入图片描述

    2.Redis实现任务队列

      redis中实现任务队列我们可以通过List中的LPUSH和RPOP命令来实现。如下:

    // 无限循环读取任务队列中的内容
    while(true){
    	String task = rpop("queue");
    	if(task != null){
    		execute(task);
    	}else{
    		// 如果没有则等待1秒钟,防止过于频繁的请求数据
    		Thread.sleep(1000);
    	}
    }
    

      上面的代码实现了一个简单的任务队列,但是还有点不完善,当任务队列中没有任务时消费者每秒都会调用RPOP命令查看是否有新任务,我们想要实现的是如果有新的任务添加进来我们能够立马知道,这时可以使用BRPOP命令来实现,BRPOP命令的作用和RPOP作用是一样的将List中最右侧的元素弹出并返回,唯一不同的是BRPOP是阻塞的。如果没有元素会一直等待到新加元素或超时。代码如下:

    // 无限循环读取任务队列中的内容
    while(true){
    	String task = brpop("queue",0);
    	// 执行任务
    	execute(task);
    }
    

    BRPOP命令接收两个参数:第一个是key,第二个是超时时间,单位是秒,0表示不限制等待时间。打开两个redis-cli实例测试如下:

    127.0.0.1:6379> brpop queue 0
    

    进入等待状态。在另一个实例中执行命令

    127.0.0.1:6379> lpush queue task
    (integer) 1
    

    阻塞的实例立马获取到了结果

    127.0.0.1:6379> brpop queue 0
    r1) "queue"
    2) "task"
    (23.39s)
    

    3.优先级队列

      实际环境中我们可能需要监听多个任务队列,有些队列的优先级比较高,需要优先执行,面对这种情况怎么办呢?这种情况下还是使用BRPOP命令来实现。
      BRPOP命令可以同时接受多个键,其语法格式为 BRPOP key [key …] timeout,如 BRPOP queue:1 queue:2 0,表示同时检测多个键,如果所有键都没有元素则阻塞。

    1. 如果其中一个键有元素则会从该键中弹出元素。
      A实例中
    127.0.0.1:6379> blpop queue:1 queue:2 0
    

    B实例中

    127.0.0.1:6379> LPUSH queue:2 task
    (integer) 1
    

    则实例A中获取的结果

    127.0.0.1:6379> blpop queue:1 queue:2 0
    1) "queue:2"
    2) "task"
    (36.98s)
    
    1. 如果多个键都有元素则按照从左到右的顺序取第一个键的元素,这条是实现优先级队列的关键
      向queue:1和queue:2中分别添加一个元素
    127.0.0.1:6379> lpush queue:1 task1
    (integer) 1
    127.0.0.1:6379> lpush queue:2 task2
    (integer) 1
    

    然后执行BRPOP命令

    127.0.0.1:6379> brpop queue:1 queue:2 0
    1) "queue:1"
    2) "task1"
    

      根据BRPOP这个特性我们就可以实现任务队列的优先级了。我们分别使用queue:confirmation.email和queue:notification.email两个键存储发送确认邮件和发送通知邮件两种任务,实现代码如下

    while(true){
    	String task = brpop("queue:confirmation.email","queue:notification.email",0);
    	execute(task);
    }
    

      这时一旦发送了确认邮件的任务被加入到 queue:confirmation.email队列中,无论 queue:notification.email还有多少任务,消费者都会优先完成发送确认邮件的任务。

    ~ok 到此为止

    展开全文
  • 任务队列任务队列是一种在线程或机器间分发任务的机制。 消息队列:消息队列的输入是工作的一个单元,称为任务,独立的职程(Worker)进程持续监视队列中是否有需要处理的新任务。 Celery 用消息通信,通常使用...
  • C++ 简单的任务队列
  • celery任务队列

    千次阅读 2020-03-08 16:55:30
    文章目录celery分布式任务队列一. celery 简介Celery 特性 :二. celery 组件1. Celery 扮演生产者和消费者的角色,2. 产生任务的方式 :3. celery 依赖三个库: 这三个库, 都由 Celery 的开发者开发和维护.三. 选择消息...
  • 主要介绍了PHP扩展Swoole实现实时异步任务队列,结合实例形式分析了PHP扩展Swoole实现实时异步任务队列相关客户端与服务器端操作技巧,需要的朋友可以参考下
  • 本文给大家介绍的是使用很简单的代码实现的多线程任务队列,给大家一个思路,希望对大家学习python能够有所帮助
  • 任务队列 Celery

    千次阅读 2018-05-31 19:45:17
    我们需要一个任务队列来进行任务的分配和维护,我们选择最常见的 Celery Celery 介绍 Celery (芹菜)是一个异步任务队列/基于分布式消息传递的作业队列 (PS:不得不说,我并不喜欢芹菜,这差点让我放弃了它 ...
  • 摸索出来这个的原因 是由于需要有序的播放多个声音的原因 需要以任务队列的形式 完成一个任务继续下一个 后面发现任务队列本身因为是后台的 发现跑同一个接口但次数很多的时候很好用
  • Celery是异步任务队列,可以独立于主进程运行,在主进程退出后,也不影响队列中的任务执行。 任务执行异常退出,重新启动后,会继续执行队列中的其他任务,同时可以缓存停止期间接收的工作任务,这个功能依赖于消息...
  • 机械机械是基于分布式消息传递的异步任务队列/作业队列。 V2实验的第一步配置自定义Logger服务器工作程序任务注册任务机械机械是基于分布式消息传递的异步任务队列/作业队列。 V2实验的第一步配置自定义Logger服务器...
  • 多线程任务队列

    2012-12-27 16:40:11
    简单的多线程任务队列
  • Android中的线程池与任务队列
  • java 任务队列

    千次阅读 2016-12-29 17:30:59
    Java任务队列在不断的学习中需要我们掌握很多相关的技术信息。 首先,下面我们就看看如何应用TaskQueue的具体问题。   Java任务队列需要我们详细的学习, 当然我们在不断的使用中还需要注意相关信息的
  • Java/Android优先级任务队列,适用于Java和Android开发人员,原理详解博客:http://blog.csdn.net/yanzhenjie1003/article/details/71773950
  • 用标准C++实现任务队列

    千次阅读 2018-11-22 13:47:59
    下面介绍一个简单的任务队列,查看完整代码。 在实现任务队列前需要定义一个接口与一个工具类 任务接口:子类实现接口的run方法来处理具体任务。 自旋锁类:用于保护任务队列的并发访问(用C++11原子操作实现)。...
  • 分布式任务队列 Celery

    千次阅读 2018-01-13 17:33:58
    分布式任务队列 Celery,Python 开发者必备技能,结合之前的 RabbitMQ 系列,深入梳理一下 Celery 的知识点。当然,这也将会是一个系列的文章。 快速入门分布式消息队列之 RabbitMQ(1) 快速入门分布式消息队列之...
  • java多线程任务队列模型

    千次阅读 2018-11-08 16:59:45
    此篇文章将从任务队列的设计;任务调度的方式(串行和并行)。代码很简单,主要是设计的思想。 任务队列 final class PendingPostQueue {  // 含有头、尾指针的链表结构实现队列  private PendingPost head;  ...
  • Unity之简易任务队列TaskQueue

    千次阅读 2017-07-09 18:31:22
    Unity之简易任务队列TaskQueue
  • JavaScript 阻塞方式实现异步任务队列

    千次阅读 2020-09-08 21:07:58
    有个需求,需要实现一个异步任务队列,并依次处理队列中的所有任务,具体如下: 随机时间增加异步任务到队列中 队列中的任务按照先进先出的规则依次执行 任务为异步请求,等一个执行完了再执行下一个 这个需求若...
  • Qt C++子线程中执行任务队列

    千次阅读 2019-04-02 18:41:49
    概述 在项目中经常会遇到这种情况,当要执行一些耗时操作的时候...所以,这里来介绍一下该场景的框架设计,如何在子线程中执行耗时任务队列。 示例 上面的描述可能不是很好理解,接下来看一个实际的用例。 假如,我...
  • queue, 创建任务队列,添加和获取作业,监视失败的任务 一个用于 1.6和 1.7的持久队列实现的集合。内容的#Table队列类型fifo一个简单的队列队列。fifottl一个简单的优先队列,支持任务时间到实时。utube一个队列内有...
  • 基于Redis的延时任务队列

    万次阅读 2019-07-17 16:38:54
    基于Redis的延时任务队列一.背景二.整体构架设计思路构架图如下:三.代码类图DelayJob(任务详情)WaitQueue(延时队列)ReadyQueue(就绪队列)Scanner(扫描线程,轮训任务)四.使用Maven依赖spring mvc中使用 一.背景  ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 452,391
精华内容 180,956
关键字:

任务队列