关于Promise和async声明的区别

题目

可以添加任务,任务包含任务数据,任务延迟触发的等待时间。
在任务到达触发时间点时,自动触发执行此任务。
队列中任务保持先进先出原则:假设 A 任务的触发等待时间为 X,B 任务的触发等待时间为 Y,B 在 A 之后被添加入队列,则 A 的前驱任务执行完成后等待时间 X 后,才执行 A,同理在 A 执行完成后,等待时间 Y,才执行 B。

思路过程

1.Java上线

读题目就是延时队列的特征,Java有锁,有多线程,写起来多方便

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class HandWritingQueue {
    public static void main(String[] args) {
        final BlockingQueue<DelayedElement> deque = new DelayQueue<>();
        Runnable producerRunnable = new Runnable() {
            int i = 10;
            public void run() {
                while (true && i>0) {
                    try {
                        --i;
                        System.out.println("producing "+i+",wait "+i+" seconds");
                        deque.put(new DelayedElement(1000 * i, "i=" + i));
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        Runnable customerRunnable = new Runnable() {
            public void run() {
                while (true) {
                    try {
                        System.out.println("consuming:" + deque.take().msg);
                        //Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Runnable getSize= new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("size="+deque.size());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        };

        Thread thread1 = new Thread(producerRunnable);
        thread1.start();

        Thread thread2 = new Thread(customerRunnable);
        thread2.start();

        Thread thread3 = new Thread(getSize);
        thread3.start();

    }

        static class DelayedElement implements Delayed {

        private final long expire;
        private final String msg;

        public DelayedElement(long delay, String msg) {
            this.msg = msg;
            expire = System.currentTimeMillis() + delay;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }
        @Override
        public int compareTo(Delayed o) {
            return  -1;//FIFO
        }
    }
}

2.Node上线

被提醒该题目可以用node实现,且不需要借助redis来做,然后我上手就是一把操作:

'use strict'
class DelayElement {
  constructor(data, expire) {
    this.data = data;
    this.expire = expire;//second
  }
}
const delayArray = [];

//push two element in delayArray
delayArray.push(new DelayElement(1, 2));
delayArray.push(new DelayElement(2, 1));
let length = delayArray.length;

let time_cnt = 0;
while (delayArray.length > 0) {
  let de = delayArray.shift();
  time_cnt += de.expire;//serial
  (function () {
    setTimeout(() => {
      console.log('expire data is :' + de.data + ',expire time is :' + de.expire);
    }, time_cnt * 1000);
  })();
}

我以为设计的考点也就是立即执行函数,延时的使用,但是这里的for循环是个伪串行,实际上是并发的,也为第三步的修改提供了bug

3.Promise时代

一开始我是想把async函数放进去,写了如下的代码:

'use strict'
const delayArray = [];
const daPush = (data, expire) => {
  delayArray.push(async () =>  {
    setTimeout(() => {
      console.log('data is ' + data + ' and expire is ' + expire);
    }, expire * 1000);
  });
}
daPush(1, 4);//2 seconds
daPush(2, 5);

(async () => {
  for (const da of delayArray) {
    await da();
  }
})();

发现代码还是串行的,然后查了一下可能的问题(以下为个人猜测,欢迎指正)async声明的函数会包装成Promise不假,但是for循环会并发去执行await中的async

4.正解

promise执行会阻塞主线程

'use strict'
const delayArray = [];
const daPush = (data, expire) => {
  delayArray.push(() => new Promise((resolve,reject) => {
    setTimeout(() => {
      if(data)
      {
        console.log('data is ' + data + ' and expire is ' + expire);
        resolve(true);
      }
      else{
        reject('there is nodata');
      }
    }, expire * 1000);
  }));
};
daPush(1, 4);//2 seconds
daPush(2, 5);

(async () => {
  for (const da of delayArray) {
    da().then((value)=>{
      // console.log(value);
    }).catch((value)=>{
      console.log(value);
    });
    //没有28-33,只35行也可以
    // await da();
  }
})();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值