定时器和promise_手写Promise核心原理,再也不怕面试官问我Promise原理

cbe54e843a0eb4f65d29d3bd33330f6f.png

整体流程的介绍

  • 整体流程的介绍

  • 1. 定义整体结构

  • 2. 实现Promise构造函数

  • 3. 实现then方法

  • 3.实现catch方法

  • 4. 实现Promise.resolve

  • 5.实现Promise.reject

  • 6.实现Promise.all

  • 7.实现Promise.race

文章会配合例子来讲解为什么要这么实现,尽我所能讲得粗俗易懂。有什么不理解或建议,欢迎下方评论。项目源码已经放到 github,顺手点个star呗:https://github.com/Sunny-lucking/howToBuildMyPromise

1. 定义整体结构

  1. 先写出构造函数,将Promise向外暴露
/*
自定义Promise函数模块:IIFE
 */

(function (window) {
    /*
    Promise构造函数
    executor:执行器函数
     */
    function Promise(executor) {

    }

    // 向外暴露Promise
    window.Promise = Promise
})()

  1. 添加Promise原型对象上的方法
 /*
    Promise原型对象的then
    指定一个成功/失败的回调函数
    返回一个新的promise对象
     */
    Promise.prototype.then = function(onResolved,onRejected){

    }

    /*
    Promise原型对象的.catch
    指定一个失败的回调函数
    返回一个新的promise对象
     */
    Promise.prototype.catch = function(onRejected){

    }
  1. 添加Promise函数对象上的方法
/*
    Promise函数对象的resovle方法
    返回一个指定结果的promise对象
     */
    Promise.resolve = function(value){

    }

    /*
    Promise函数对象的reject方法
    返回一个指定reason的失败状态的promise对象
    */
    Promise.reject = function(value){

    }

    /*
    Promise函数对象的all方法
    返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功
    */
    Promise.all = function(0value){

    }

    /*
    Promise函数对象的race方法
    返回一个promise对象,状态由第一个完成的promise决定
    */
    Promise.race = function(value){

    }

通过上面的注释可以知道。不管是Promise原型对象上的方法还是Promise函数对象上的方法 ,它们的执行结果都将返回一个Promise对象

2. 实现Promise构造函数

我们看看我们是怎么使用Promise的

const promiseA = new Promise( (resolve,reject) => {
    resolve(777);
});
  1. 我们传入了一个函数,而且这个函数被立即执行,不仅如此,这个函数还会立即执行resolve和reject。说明构造函数里有resolve和reject方法。因此我们可以初步实现:
    /*
    Promise构造函数
    executor:执行器函数
     */
    function Promise(executor) {

        function resovle() {

        }
        function reject() {

        }

        // 立即同步执行executor
        executor(resovle,reject)
    }

  1. 每个promise都有一个状态可能为pending或resolved,rejected。而且初始状态都为pending。因此需要添加个status来表示当前promise的状态.。并且每个promise有自己的data。
function Promise(executor) {

        var self = self
        新增代码
        self.status = 'pending' // 给promise对象指定status属性,初始值为pending
    
        self.data = undefined // 给promise对象指定一个存储结果的data

        function resovle() {

        }
        function reject() {

        }

        // 立即同步执行executor
        executor(resovle,reject)
    }

此外,当我们这样使用Promise的时候,

// 例1
var promise = new Promise((resovle,reject)=>{
    
})

promise.then(resolve=>{},reject=>{})

这时执行到then,因为我们传入的立即执行函数没有执行resolve或者reject,所以promise的状态还是pending,这时要把then里面的回调函数保存起来,所以需要个callbacks数组

function Promise(executor) {

        var self = self

        self.status = 'pending' // 给promise对象指定status属性,初始值为pending
        self.data = undefined // 给promise对象指定一个存储结果的data
        新增代码
        self.callbacks = []  // 每个元素的结构:{onResolved(){},onRejected(){}}


        function resovle() {

        }
        function reject() {

        }

        // 立即同步执行executor
        executor(resovle,reject)
    }

那 then函数是怎么把传入的回调收集起来的。其实很简单,就是判断当前promise是否为pending状态,是的话,就把回调push到callbacks中。

Promise.prototype.then = function(onResolved,onRejected){

        var self = this
        
        if(self.status === 'pending'){
            // promise当前状态还是pending状态,将回调函数保存起来
            self.callbacks.push({
                onResolved(){onResolved(self.data)},
                onRejected(){onRejected(self.data)}
            })
        }else if(self.status === 'resolved'){
        }else{
        }

    }
  1. 在上面的例子1的基础上,当我们执行resovle(value)时,如例2
// 例2
var promise = new Promise((resolve,reject)=>{
    setTimeout(function () {
        resolve(1)
    })
})

promise.then(
    value=>{console.log(value)},
    err=>{console.log(err)}
    )

此时代码执行情况是怎么样的呢?

  1. 先执行new Promise里的代码,然后发现个定时器,js线程将定时器交给定时器线程处理,2. 然后继续执行下面的代码,发现是then,而且当前的promise还是pending的状态。就把then里的回调函数放到callbacks中。
  2. 5秒后定时器线程将定时器里的回调函数(也就是宏任务)放到消息队列中,js线程在消息队列里发现了这个宏任务,就把它拿来执行。
  3. 执行这个宏任务,就执行了resolve(1),此时promise的callbacks里的回调被执行。并将当前promise状态改为resolved。然后这个1也会被保存到当前promise对象中

那怎么实现resolve呢?依旧上面的描述,就知道resovle的功能是执行callbacks里的函数,并保存data并将当前promise状态改为resolved。所以我们可以这么实现

function resolve(value) {
    // 将状态改为resolved
    self.status = 'resolved'
    // 保存value的值
    self.data = value

    // 如果有待执行的callback函数,立即异步执行回调函数onResolved
    if (self.callbacks.length>0){
        self.callbacks.forEach(callbackObj=>{
            callbackObj.onResolved(value)
        })
    }
}
  1. 我们还知道,promise的状态只能改变一次,因此当执行resolve的时候要判断是不是promise是不是pending的状态,否则是不能执行的
function resolve(value) {
    // 如果当前状态不是pending,则不执行
    if(this.status !== 'pending'){
        return 
    }
    // 将状态改为resolved
    this.status = 'resolved'
    // 保存value的值
    this.data = value

    // 如果有待执行的callback函数,立即异步执行回调函数onResolved
    if (this.callbacks.length>0){
        setTimeout(()=>{
            this.callbacks.forEach(callbackObj=>{ A
                callbackObj.onResolved(value)
            })
        })
    }
}
  1. 异曲同工之妙的是reject方法也是这个道理,因此这里无需赘述
function reject(value) {
    // 如果当前状态不是pending,则不执行
    if(self.status !== 'pending'){
        return
    }
    // 将状态改为rejected
    self.status = 'rejected'
    // 保存value的值
    self.data = value

    // 如果有待执行的callback函数,立即异步执行回调函数onResolved
    if (self.callbacks.length>0){
      self.callbacks.forEach(callbackObj=>{
          callbackObj.onRejected(value)
      })
    }
}
  1. 我们又知道,当在执行executor的时候,如果执行异常的话,这个promise的状态会直接执行reject方法。例如
// 例 3
var promise = new Promise((resolve,reject)=>{

    error;执行到这里出错了

    setTimeout(function () {
        resolve(1)
    })
})

要实现这个功能,我们可以在executor外让try catch来捕获

try{
    // 立即同步执行executor
    executor(resolve,reject)
}catch (e) { // 如果执行器抛出异常,promise对象变为rejected状态
    reject(e)
}

好了,现在测试下

 // 例4
 let promise = new Promise((resolve,reject)=>{
        
        setTimeout(function () {
            resolve(1)
            //reject(1)
        },100)
    })

    promise.then(
        value=>{
            console.log("onResolved:",value);
        },
        reason=>{
            console.log("onRejected:",reason);
        }
    )

发现成功。成功输出onResolved:1

3. 实现then方法

我们在上面简单的实现了当前promise为pending状态的情况,如:

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    if(self.status === 'pending'){
        // promise当前状态还是pending状态,将回调函数保存起来
        self.callbacks.push({
            onResolved(){onResolved(self.data)},
            onRejected(){onRejected(self.data)}
        })
    }else if(self.status === 'resolved'){
    }else{
    }

}

那其他情况呢?

执行到then时,promise可能会是pending状态,此时就要把then里的回调函数保存起来,也可能会是resolved或者rejected状态,此时就不用把回调保存起来,直接执行onResolved或onRejected方法。注意是异步执行。而且是做为微任务的,这里我们简单的用setTimeout来实现就好了。

Promise.prototype.then = function(onResolved,onRejected){

  var self = this

  if(self.status === 'pending'){
      // promise当前状态还是pending状态,将回调函数保存起来
      self.callbacks.push({
          onResolved(){onResolved(self.data)},
          onRejected(){onRejected(self.data)}
      })
  }else if(self.status === 'resolved'){
      setTimeout(()=>{
          onResolved(self.data)
      })
  }else{
      setTimeout(()=>{
          onResolved(self.data)
      })
  }

}

而且我们知道,执行完then是要返回一个新的promise的,而新的promise的状态则由当前then的执行结果来确定。

 Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{
        if(self.status === 'pending'){
            // promise当前状态还是pending状态,将回调函数保存起来
            self.callbacks.push({
                onResolved(){onResolved(self.data)},
                onRejected(){onRejected(self.data)}
            })
        }else if(self.status === 'resolved'){
            setTimeout(()=>{
                onResolved(self.data)
            })
        }else{
            setTimeout(()=>{
                onResolved(self.data)
            })
        }
    })

}

当 当前的promise状态为resolved的时候,则执行then的时候,会执行第二个判断语句

则当前执行第二个判断语句的时候会出现三种情况

  1. 如果then里的回调函数返回的不是promise,return的新promise的状态是则是resolved,value就是返回的值。例如:
// 例5
let promise = new Promise((resolve,reject)=>{
    resolve(1)
})

promise.then(
    value=>{
        return value //返回的不是promise,是value
    }
)

因此,我们可以这样实现

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{
        if(self.status === 'pending'){
            // promise当前状态还是pending状态,将回调函数保存起来
            self.callbacks.push({
                onResolved(){onResolved(self.data)},
                onRejected(){onRejected(self.data)}
            })
        }else if(self.status === 'resolved'){
            修改代码
            setTimeout(()=>{
                const result = onResolved(self.data)
                if (result instanceof Promise){

                } else {
                // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。
                    resolve(result)
                }
            })
        }else{
            setTimeout(()=>{
                onResolved(self.data)
            })
        }
    })

}

简单解释下:

执行onResolved(self.data),其实就是执行例子中的下面这个回调函数

value=>{
        return value //返回的不是promise,是value
    }

那么这个回调函数返回了value。就把value传入resolve函数,resolve函数将当前新的promise的状态改为resolved,同时将value保存到当前新的promise的data中。

  1. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果,如代码所示,我们返回一个新的promise。如果这个promise执行了resolve,返回的新的promise的状态则是resolved的。否则为rejected
// 例6
let promise = new Promise((resolve,reject)=>{
    resolve(1)
})

promise.then(
    value=>{
        return new Promise((resolve,reject)=>{
            resolve(2)
            //或者
            //reject(error)
        })
    }
)

因此我们可以这样实现

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{
        if(self.status === 'pending'){
            // promise当前状态还是pending状态,将回调函数保存起来
            self.callbacks.push({
                onResolved(){onResolved(self.data)},
                onRejected(){onRejected(self.data)}
            })
        }else if(self.status === 'resolved'){
            setTimeout(()=>{
                const result = onResolved(self.data)
                if (result instanceof Promise){
                    // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果
                    result.then(
                        value => {resolve(value)},
                        reason => {reject(reason)}
                    )
                } else {
                    // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。
                    resolve(result)
                }
            })
        }else{
            setTimeout(()=>{
                onResolved(self.data)
            })
        }
    })

}

在这里说明一下:

result.then(
    value => {resolve(value)},
    reason => {reject(reason)}
)

由于我们在例6中执行了then里的

value=>{
        return new Promise((resolve,reject)=>{
            resolve(2)
            //或者
            //reject(error)
        })
    }

则返回一个promise对象,这个promise对象可能为resolved状态(执行 resolve(2))也可能为rejected状态(执行reject(error))。

将会导致value => {resolve(value)},这个回调函数的执行或者reason => {reject(reason)}的执行。

因此会把即将返回的新的promise的data设置为value或者,reason。会把状态设置为resolved或者rejected。

  1. 如果执行这段代码的时候抛出错误,则返回的promise的状态为rejected,我们可以用try catch来实现
setTimeout(()=>{
    try{
        const result = onResolved(self.data)
        if (result instanceof Promise){
            // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果
            result.then(
                value => {resolve(value)},
                reason => {reject(reason)}
            )
        } else {
            // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。
            resolve(result)
        }
    }catch (e) {
      //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected
        reject(e)
    }
})

异曲同工之妙的是当status === 'rejected',道理一样

 setTimeout(()=>{
      try{
          const result = onRejected(self.data)
          if (result instanceof Promise){
              // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果
              result.then(
                  value => {resolve(value)},
                  reason => {reject(reason)}
              )
          } else {
              // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。
              resolve(result)
          }
      }catch (e) {
          //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected
          reject(e)
      }
  })

到这里,我们发现当执行resolve的时候,onResolved(self.data)onRejected(self.data)执行时也会跟上面一样的结果,可以说执行回调函数都要做以上判断,因此我们要将

 self.callbacks.push({
    onResolved(){onResolved(self.data)},
    onRejected(){onRejected(self.data)}
})

改成

if(self.status === 'pending'){
// promise当前状态还是pending状态,将回调函数保存起来
self.callbacks.push({
    onResolved(){
        try{
            const result = onResolved(self.data)
            if (result instanceof Promise){
                // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果
                result.then(
                    value => {resolve(value)},
                    reason => {reject(reason)}
                )
            } else {
                // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。
                resolve(result)
            }
        }catch (e) {
            //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected
            reject(e)
        }
    },

到此,我们发现,相同的代码太多了,因此有必要封装一下

 function handle(callback) {
    try{
        const result = callback(self.data)
        if (result instanceof Promise){
            // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果
            result.then(
                value => {resolve(value)},
                reason => {reject(reason)}
            )
        } else {
            // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。
            resolve(result)
        }
    }catch (e) {
        //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected
        reject(e)
    }
}

这样以来就清爽了很多

   Promise.prototype.then = function(onResolved,onRejected){

        var self = this

        return new Promise((resolve,reject)=>{
           /*
            调用指定回调函数的处理,根据执行结果。改变return的promise状态
             */
            function handle(callback) {
                try{
                    const result = callback(self.data)
                    if (result instanceof Promise){
                        // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果
                        result.then(
                            value => {resolve(value)},
                            reason => {reject(reason)}
                        )
                    } else {
                        // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。
                        resolve(result)
                    }
                }catch (e) {
                    //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected
                    reject(e)
                }
            }
            if(self.status === 'pending'){
                // promise当前状态还是pending状态,将回调函数保存起来
                self.callbacks.push({
                    onResolved(){
                        handle(onResolved)
                    },
                    onRejected(){
                        handle(onRejected)
                    }
                })
            }else if(self.status === 'resolved'){
                setTimeout(()=>{
                    handle(onResolved)
                })
            }else{ // 当status === 'rejected'
                setTimeout(()=>{
                    handle(onRejected)
                })
            }
        })

    }

另外,我们还知道,promise会发生值传透,例如


let promsie = new Promise((resolve,reject)=>{
    resolve(1)
})
promsie
  .then(2)
  .then(3)
  .then(value =>console.log(value))

运行结果:1

解释:.then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。值传透可以理解为,当传入then的不是函数的时候,这个then是无效的。而实际原理上其实是当then中传入的不算函数,则这个then返回的promise的data,将会保存上一个的promise.data。这就是发生值穿透的原因。而且每一个无效的then所返回的promise的状态都为resolved

因此,要实现直传透这个特性,我们可以这样实现

添加这两句来判断要不要发生值传透

onResolved = typeof onResolved === 'function'? onResolved: value => value
onRejected = typeof onRejected === 'function'? onRejected: reason => {throw reason}

实际上就是改写,如果传入的不是函数,那就忽略那个传入值,自己再写一个函数。这个函数的执行结果将返回上一个promise的data

Promise.prototype.then = function(onResolved,onRejected){
    onResolved = typeof onResolved === 'function'? onResolved: value => value
    onRejected = typeof onRejected === 'function'? onRejected: reason => {throw reason}
    var self = this

    return new Promise((resolve,reject)=>{

        /*
        调用指定回调函数的处理,根据执行结果。改变return的promise状态
         */
        function handle(callback) {
            try{
                const result = callback(self.data)
                if (result instanceof Promise){
                    // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果
                    result.then(
                        value => {resolve(value)},
                        reason => {reject(reason)}
                    )
                } else {
                    // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。
                    resolve(result)
                }
            }catch (e) {
                //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected
                reject(e)
            }
        }
        if(self.status === 'pending'){
            // promise当前状态还是pending状态,将回调函数保存起来
            self.callbacks.push({
                onResolved(){
                    handle(onResolved)
                },
                onRejected(){
                    handle(onRejected)
                }
            })
        }else if(self.status === 'resolved'){
            setTimeout(()=>{
                handle(onResolved)
            })
        }else{ // 当status === 'rejected'
            setTimeout(()=>{
                handle(onRejected)
            })
        }
    })

}

3.实现catch方法

catch方法的作用跟then里的第二歌回调函数一样,因此我们可以这样来实现

Promise.prototype.catch = function(onRejected){
    return this.then(undefined,onRejected)
}

我的天啊,居然这么简单

4. 实现Promise.resolve

我们都知道,Promise.resolve方法可以传三种值

  1. 不是promise
  2. 成功状态的promise
  3. 失败状态的promise

    Promise.resolve(1)
    Promise.resolve(Promise.resolve(1))
    Promise.resolve(Promise.reject(1))

实际上跟实现上面的then时有点像

Promise.resolve = function(value){
  return new Promise((resolve,reject)=>{
      if (value instanceof Promise){
          // 如果value 是promise
          value.then(
              value => {resolve(value)},
              reason => {reject(reason)}
          )
      } else{
          // 如果value不是promise
          resolve(value)
      }

  }

}

5.实现Promise.reject

实现这个比较简单,返回一个状态为rejected的promise就好了

/*
Promise函数对象的reject方法
返回一个指定reason的失败状态的promise对象
*/
Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason)
    })
}

6.实现Promise.all

我们知道,这个方法会返回一个promise

    /*
    Promise函数对象的all方法
    返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功
    */
    Promise.all = function(promises){
        return new Promise((resolve,reject)=>{
           
        })
    }
  

而这个promise的状态由遍历每个promise产生的结果决定

    /*
    Promise函数对象的all方法
    返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功
    */
    Promise.all = function(promises){
        return new Promise((resolve,reject)=>{
            // 遍历promises,获取每个promise的结果
            promises.forEach((p,index)=>{
                
            })
        })
    }

有两种结果:

  1. 遍历到有一个promise是reject状态,则直接返回的promise状态为rejected
 Promise.all = function(promises){
        return new Promise((resolve,reject)=>{
            // 遍历promises,获取每个promise的结果
            promises.forEach((p,index)=>{
                p.then(
                    value => {
    
                    },
                    reason => { //只要有一个失败,return的promise状态就为reject
                        reject(reason)
                    }
                )
            })
        })
    }
  1. 遍历所有的promise的状态都为resolved,则返回的promise状态为resolved,并且还要每个promise产生的值传递下去
   Promise.all = function(promises){
      const values = new Array(promises.length)
      var resolvedCount = 0 //计状态为resolved的promise的数量
      return new Promise((resolve,reject)=>{
          // 遍历promises,获取每个promise的结果
          promises.forEach((p,index)=>{
              p.then(
                  value => {
                      // p状态为resolved,将值保存起来
                      values[index] = value
                      resolvedCount++;
                      // 如果全部p都为resolved状态,return的promise状态为resolved
                      if(resolvedCount === promises.length){
                          resolve(values)
                      }
                  },
                  reason => { //只要有一个失败,return的promise状态就为reject
                      reject(reason)
                  }
              )
          })
      })
  }

好像可以了,当其实这里还有一个问题,就是all传进去的数组不一定都是promise对象,可能是这样的

all([p,2,3,p])

因此需要把不是promise的数字包装成promise

    Promise.all = function(promises){
        const values = new Array(promises.length)
        var resolvedCount = 0 //计状态为resolved的promise的数量
        return new Promise((resolve,reject)=>{
            // 遍历promises,获取每个promise的结果
            promises.forEach((p,index)=>{
                Promise.resolve(p).then(
                    value => {
                        // p状态为resolved,将值保存起来
                        values[index] = value
                        resolvedCount++;
                        // 如果全部p都为resolved状态,return的promise状态为resolved
                        if(resolvedCount === promises.length){
                            resolve(values)
                        }
                    },
                    reason => { //只要有一个失败,return的promise状态就为reject
                        reject(reason)
                    }
                )
            })
        })
    }

7.实现Promise.race

这个方法的实现要比all简单很多

  /*
    Promise函数对象的race方法
    返回一个promise对象,状态由第一个完成的promise决定
    */
    Promise.race = function(promises){
        return new Promise((resolve,reject)=>{
            // 遍历promises,获取每个promise的结果
            promises.forEach((p,index)=>{
                Promise.resolve(p).then(
                    value => {
                        // 只要有一个成功,返回的promise的状态九尾resolved
                        resolve(value)

                    },
                    reason => { //只要有一个失败,return的promise状态就为reject
                        reject(reason)
                    }
                )
            })
        })
    }

有什么不理解或建议,欢迎下方评论。项目源码已经放到github:https://github.com/Sunny-lucking/howToBuildMyPromise  顺手点个star呗

去做一下题,看看是不是真的掌握了呢?【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理)

之前可能会出现有些题不会做,而当你阅读完这篇文章后,再去做,发现易如反掌。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/350655.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Java 9中使用sun.misc.Unsafe

Java 9 EA版本已经发布,现在我们可以看到如何使用sun.misc.Unsafe。 我领导了公开运动,以保留对Java 9的访问,该访问最终成功,从而导致对JEP 260的修订。 那么,事情如何结束? 设定 首先,您需要…

惊现神作!!!

发现穿越类小说 《穿越位面的狂人》 起点地址: https://book.qidian.com/info/1010641845 小说名《位面穿梭之宿舍电梯》改为《穿越位面的狂人》nx大学大一学生柳风,因经济拮据,不得不住在宿舍楼顶的一间破屋子里,半夜下楼上厕…

[HNOI2019]校园旅行

题目 过于神仙啊,抄题解.jpg 首先\(n\)并不是很大啊,我们可以直接用\(f_{i,j}\)表示\(i\)到\(j\)是否存在一个回文路径 对于一条回文路径,如果在两端分别添加一个相同的字符,那么仍然是一个回文路径,于是我们可以利用这…

Your CPU supports instructions that this TensorFlow binary was not compiled to use AVX AVX2

大致的原因就是说:tensorflow觉得你电脑cpu还行,支持AVX(Advanced Vector Extensions),运算速度还可以提升,所以可以开启更好更快的模式,但是你现在用的模式相对来说可能不是那么快,…

安卓 sharedpreferences可以被其它activity读取_Google|再见 SharedPreferences 拥抱 Jetpack DataStore...

Google 新增加了一个新 Jetpack 的成员 DataStore,主要用来替换 SharedPreferences, DataStore 应该是开发者期待已久的库,DataStore 是基于 Flow 实现的,一种新的数据存储方案,它提供了两种实现方式:Proto…

【20171025早】alert(1) to win 练习

本人黑绝楼,自称老黑,男,25岁,曾经在BAT工作过两年,但是一直都是底层人员,整天做重复性工作,甚敢无趣,曾和工作十年之久的同事聊天,发现对方回首过往,生活是寡…

Arduino 与 SPI 结合使用 以及SPI 深层理解

本文主要讲解两部分内容,不做任何转发,仅个人学习记录: 一. Arduino 与 SPI 结合使用 : 二. SPI 深层理解 有价值的几个好的参考: 1. 中文版: https://blog.csdn.net/xxxxxx91116/article/details/42620413 这版本适…

VGG

VGG16网络,卷积核3*3,步长为1,填充(padding)为1; 池化2*2,步长为2 全连接层 卷积核1*1 Input Layer:224*224*3图像 Conv1-1 Layer:包含64个卷积核,kernal s…

guava 并发同步_Google Guava –与Monitor同步

guava 并发同步Google Guava项目是每个Java开发人员都应该熟悉的库的集合。 Guava库涵盖了I / O,集合,字符串操作和并发性。 在这篇文章中,我将介绍Monitor类。 Monitor是一种同步构造,可以在使用ReentrantLock的任何地方使用。 随…

qt 定时器_Qt开源作品23-颜色拾取器

## 一、前言在做很多项目的UI界面的时候,相信绝大部分人都有过抄袭别人的UI界面尤其是颜色的时候,毕竟十个程序员九个没有审美,或者说审美跟一坨屎一样,大家主要的精力以及擅长点都是在写功能实现具体功能上面,这个事情…

第5章学习小结

第五章主要学习了树的知识,以前一直很好奇,为什么电脑能存储像树一样的数据结构,学完才发现,ADT加数组或者ADT加链表真的可以衍生出多种多样的数据类型,以下做出本章小结: 1.利用ASCII码实现不同类型的数据…

tf.transpose

tf.transpose(input, [dimension_1,dimenaion_2,..,dimension_n]) 这个函数主要适用于交换输入张量的不同维度用的,如果输入张量是二维,就相当是转置。dimension_n是整数,如果张量是三维,就是用0,1,2来表示。这个列表里的每个数对…

【20171025中】alert(1) to win 脚本渲染自建

游戏误人生&#xff0c;一下午玩了将近四个小时的三国杀&#xff0c;后悔不已&#xff0c;然后重新拾起xss challenge&#xff0c;突发奇想&#xff0c;自己构建渲染后的html。 从最简单的开始。 自动检测html: <!DOCTYPE html> <html> <head><meta http-…

使用JPA和@NamedQueries的Spring数据

如果在JPA实体上使用Spring Data和NamedQuery批注&#xff0c;则可以使用spring数据存储库以更方便的方式轻松使用它们。 在先前的博客中&#xff0c;我们使用spring boot和docker 创建了spring数据项目。 我们将使用相同的项目并增强存储库的功能。 我们将实现一个命名查询&…

vs无法写入量的大数据_一个每天服务数万人的企业食堂:自助餐按重计价,大数据支持食材预备量...

钱江晚报小时新闻记者 祝瑶 昨天下午6点多&#xff0c;钱报记者来到杭州阿里巴巴总部。这里共有5个员工食堂&#xff0c;几乎覆盖了全国各地的口味&#xff0c;每天为数万阿里人服务。其中&#xff0c;最当红的是2号食堂&#xff0c;除了有丰俭由人的自助餐区&#xff0c;还有十…

6号板编译失败找不到arm-none-linux-gnueabi-gcc

明明已经添加到/etc/environment 安装sudo apt-get install lib32z1 lib32ncurses5转载于:https://www.cnblogs.com/xpylovely/p/10817240.html

tf.train.Saver

将训练好的模型参数保存起来&#xff0c;以便以后进行验证或测试&#xff0c;这是我们经常要做的事情。tf里面提供模型保存的是tf.train.Saver()模块。 模型保存&#xff0c;先要创建一个Saver对象&#xff1a;如 savertf.train.Saver() 在创建这个Saver对象的时候&#xff…

Neo4j:空值如何工作?

我时不时地发现自己想将CSV文件导入Neo4j&#xff0c;而我总是对如何处理可能潜伏在其中的各种空值感到困惑。 让我们从一个没有CSV文件的示例开始。 考虑以下列表&#xff0c;以及我尝试仅返回空值的尝试&#xff1a; WITH [null, "null", "", "Ma…

楼层钢筋验收会议纪要_钢筋施工质量通病防治

一、钢筋原材1、钢筋表面出现黄色浮锈&#xff0c;严重转为红色&#xff0c;日久后变成暗褐色&#xff0c;甚至发生鱼鳞片剥落现象。图片原因保管不良&#xff0c;受到雨雪侵蚀&#xff0c;存放期长&#xff0c;仓库环境潮湿&#xff0c;通风不良。防 治 措 施1、钢筋原料应存放…

simulink代码生成(一)——环境搭建

一、安装C2000的嵌入式环境&#xff1b; 点击matlab附加功能&#xff0c; 然后搜索C2000&#xff0c;安装嵌入式硬件支持包&#xff1b;点击安装即可&#xff1b;&#xff08;目前还不知道破解版的怎么操作&#xff0c;目前我用的是正版的这样&#xff0c;完全破解的可能操作…