async和await用法理解和快速上手 , 同步任务和异步任务顺序安排和轻松理解 , js代码执行顺序表面知道
学习关键语句 :
async , await 用法
await 怎么使用
同步任务和异步任务
微任务和宏任务
js中代码执行顺序
写在前面
虽然说 async 和 await 是 Promise 的语法糖 , 但是用惯了Promise 的人(我) , 还真不能超快速使用上这个语法糖 , 所以赶紧写一篇文章出来让各位了解了解这个到底怎么用在我的项目中呢 , 毕竟大家都是想用在项目里的 , 而不是说简单的学习一下语法 难道只有我看了语法介绍还是不会用嘛
同时 这一部分和异步任务有很大的关系 , 因为一般 await 我们是在发起请求时使用的 , 所有我们同样也会看看 js 中的同步任务和异步任务
而且我们从异步任务开始会更好的理解了 await 的用法
而异步任务需要从同步任务开始
这篇文章的目的就是希望用最简单的话来说明白上面这一些东东
警告 ! 本文可能带有知识误导 , 得出的结论相不相信取决于自己 , 作者说.
开始
同步任务和异步任务
- 同步任务
低情商 : 不会吧 , 不会真有人来看同步任务是啥吧 ?
低情商解答 : 上一行代码不执行完下一行代码就不开始执行 , 这就是同步 , 而执行就是任务
高情商 : 兄弟们又来复习啦 , 温故而知新啊
高情商解答 : JavaScript 是一门单线程语言 , 这意味着对于你写的 js 代码 , 他的执行顺序必然是从上往下一行一行执行的 , 一旦哪行出错了 , 那整个程序都会停止运行 , 所以一行一行做任务我们称之为同步任务
- 异步任务
异步任务简单来说 , 就是他不是同步任务
啊这是在说 , 结合上面同步任务的意思 , 异步任务就不会一行一行的执行 , 他超脱了原本的代码执行顺序 , 异步任务有自己执行的时候 , 这个一会儿再看什么时候执行
异步任务分为两种 , 微任务 和 宏任务 , 列举一些常见的
微任务
Promise.then async await
宏任务
setTimeout setInterval
对于这一块只需记住 , 从执行顺序上微任务是要先于宏任务的
Promise.then
.then 的微任务
我们现在已经知道了 Promise.then 是一种微任务 , 同时我们还知道微任务是异步任务的一种 , 并且你还突然想起来异步任务不是同步任务 淦整天记的都啥
我们来看一段简单的代码 , 以下代码可以直接在浏览器按 F12 在控制台开始测试
function getP() {return new Promise((resolve, reject) => {console.log(0)resolve()})
}
getP().then(() => console.log(1))
console.log(2)
我们可以看到打印的顺序是 0 2 1
解释:
已知 : 按照顺序先执行 Promise() , 再执行 .then() , 最后执行 console.log(2)
但是又已知 .then() 是微任务 , 所以就跳出了同步任务 , 在最后执行打印 1 的任务
.then 的使用场景
众所周知 , 我们在发起请求之后 , 就会在回调中使用返回的数据 , 这就是最常见的使用场景了
我们看看下面这段代码
function getP() {return new Promise((resolve, reject) => {resolve({data:{id:1}})})
}
let userId = -1
getP().then(res => userId = res.data.id)
我们为了获得用户的 Id , 必须向后台发起请求 , 并在回调中赋值给页面中的数据
而有时候我们需要先通过上一个请求获取到数据 , 再使用这个数据进行下一次请求 , 简单来说就是请求的嵌套
请看下面这段代码 , 这是正常使用 promise.then 来获取数据再通过数据发起请求的做法
function getP(id = -1) {console.log(id)return new Promise((resolve, reject) => {resolve({data:{id:1}})})
}
let userId = -1
getP().then(res => {userId = res.data.idgetP(userId).then(() => {})
})
其实这样倒也没什么问题 , 只是如果需要请求的次数变多 , 还是会出现类似于回调地狱的情况 , 所以才会又出现了 async 和 await 的语法糖
async 和 await
关于这俩只需要记住关键的点就足够了
- async 和 await 是成双成对的 , 但是使用 async 可以不带 await , 使用 await 必须带上 async
- 使用 async 修饰的函数必定返回一个 promise 对象 , 如果该函数没有返回值 , 那返回的 promise 对象的成功回调参数为 undefined ; 如果有返回值且不为 promise , 那么返回值是什么成功回调参数就是什么 ; 如果返回值是 promise , 那就不用再说了
- 使用 await 修饰的请求方法回调将会阻塞当前方法下面的代码执行 , 必须先执行完请求的回调才可以执行下面的代码 , 当然了 await 默认是成功的回调 , 其他回调也可以自己手写
- 同时 , await 阻塞请求方法下面的代码执行会影响到 async 函数下方的代码执行 , 这个先使用了再说
学习使用
啥也不说了 , 先赶紧学会怎么用 async 和 await 取代 promise 的使用吧
同样是上面的需求
function getP(id = -1) {console.log(id)return new Promise((resolve, reject) => {resolve({data:{id:1}})})
}
async function get(){let res = await getP()getP(res?.data?.id)
}
get()
可以看到 , 第 8 行的 res 确实拿到了值并且传递给下一次请求成功打印出了 1
那如果不加 await 呢?
function getP(id = -1) {console.log(id)return new Promise((resolve, reject) => {resolve({data:{id:1}})})
}
function get(){let res = getP()getP(res?.data?.id)
}
get()
我们可以看到 , 两次的打印结果都是 -1 , 说明第二次并没有值传递进来
好这样子就可以用 async 和 await 替换 promise 发起请求了
await 的理解与探究
await 的作用实际上就是 阻塞代码执行 , 必须先执行完当前这行代码才能走下去 , 相当于将这行代码以下的代码全部转变成了微任务
请先看我得出的两条结论 , 我们将根据这两条结论解读下面的代码逻辑
- 遇到 await 时 , 可以视为将此 await 所在作用域内 await 下方的代码整块全部堵塞 , 堵塞可以视为塞入微任务队列中
- 堵塞的代码中包括的 .then 之内和之后的两部分 , 必须要等待 .then 之内的代码执行完成后 , 才能执行 .then 之后的代码 , 必须要等待 .then 之后的代码执行完成后 , 才能执行堵塞代码所在函数的下一行代码 , 其中需要等待的包括同步任务和微任务 , 而宏任务则统一加入到宏任务队列中
注意 : 对于 await.then 中的嵌套 async 和 await 同样满足上述两条结论 , 而对于 await.then 中的非 await 请求 , 则按照 await.then 中的正常情况处理
使用 await
请看以下代码为例子:
代码一
// 打印一个 -1 , 然后返回一个 promise 对象并执行成功回调
function getP() {console.log('-1')return new Promise((resolve, reject) => {resolve(1)})
}
// 创立一个定时器 , 并且马上打印输入的参数
function timer(a) {setTimeout(() => {console.log(a)}, 1);
}
// 声明一个函数 , 主要就是调用这个方法
async function testP() {console.log('0')await getP().then(async () => {console.log('1')timer('2')await getP().then(res => {console.log('3')getP().then(() => console.log('4'))console.log('5')})console.log('6')timer('7')})console.log('8')getP().then(() => console.log('9'))console.log('10')
}
// 声明我们要使用的函数 , 其中调用了上述所有的方法
function test() {timer('11')testP().then(() => {console.log('12')})timer('13')console.log('同步代码最后一句')
}
// 使用函数
test()
我们先来看下执行结果
接下来我们逐行对上述代码执行过程进行解释 , 请看以下截图 , 因为有行号好讲很多
- 第 112 行执行 test 函数 , 进入第 104 行 , 发现是一个打印 11 的定时器 , 现在将它加入宏任务队列中
此时 , 以下没有就是空
打印:
微任务队列:
宏任务队列: 11
- 进入第 105 行 , 执行 testP 函数 , 进入第 83 行 , 直接打印 0
此时 , 以下没有就是空
打印: 0
微任务队列:
宏任务队列: 11
- 进入第 84 行 , 执行 getP 函数 , 立马打印 -1 , 由于突然发现 getP 函数前面使用了 await 进行修饰 , 根据结论一 , 所以将 getP 之后的代码执行全部阻塞 , 可以看做是微任务等待处理 , 可以等同看做加入微任务队列
此时 , 以下没有就是空
打印: 0 -1
微任务队列: 阻塞代码
宏任务队列: 11
阻塞代码: 第 85 行 到 第 101 行
- 由于 testP 函数中没有同步任务后 , 继续回到第 106 行 , 发现 .then 是 testP 函数的微任务 , 将里面的内容打印 12 加入到微任务队列
此时 , 以下没有就是空
打印: 0 -1
微任务队列: 阻塞代码 12
宏任务队列: 11
阻塞代码: 第 85 行 到 第 101 行
- 进入第 109 行 , 定时器是宏任务 , 将打印 13 加入到宏任务队列
此时 , 以下没有就是空
打印: 0 -1
微任务队列: 阻塞代码 12
宏任务队列: 11 13
阻塞代码: 第 85 行 到 第 101 行
- 进入第 110 行 , 同步任务直接打印 ‘同步代码最后一句’
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’
微任务队列: 阻塞代码 12
宏任务队列: 11 13
阻塞代码: 第 85 行 到 第 101 行
- test 函数执行完毕 , 同步任务已经全部完成 , 开始执行微任务队列中的代码 , 遇到阻塞代码 , 开始逐行执行 , 第 86 行直接打印 1 , 第 87 行将打印 2 加入宏任务队列 , 第 88 行执行 getP 函数直接打印 -1 , 发现使用 await 修饰 , 根据结论一 , 将 await.then 下的代码进行堵塞
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1
微任务队列: 阻塞代码 12
宏任务队列: 11 13 2
阻塞代码: 第 90 行 到 第96 行 , 第 98 行 到 第 101 行
- 根据结论二 , 由于第 90 行 到 第 96 行处在第 84 行的 await.then 内且不为宏任务 , 所以需要等待第 96 行代码执行完后才能继续执行第 98 行 , 进入第 90 行 , 直接打印 3
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1 3
微任务队列: 阻塞代码 12
宏任务队列: 11 13 2
阻塞代码: 第 90 行 到 第96 行 , 第 98 行 到 第 101 行
- 进入第 91 行 , 直接打印 -1 , 进入第 92 行 , 由于没有 await 修饰 , 根据结论下的注意点 , 这里按照正常将打印 4 的任务加入微任务队列 , 然后进入第 93 行直接打印 5
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1 3 -1 5
微任务队列: 阻塞代码 12 4
宏任务队列: 11 13 2
阻塞代码: 第 98 行 到 第 101 行
- 此时应该进入第 95 行 , 但是根据结论二 , 需要等待 await.then 中的代码包括同步任务和微任务全部完成才能执行第 95 行 , 所以退回第 92 行将微任务队列中的 4 提前打印为 4
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1 3 -1 5 4
微任务队列: 阻塞代码 12
宏任务队列: 11 13 2
阻塞代码: 第 98 行 到 第 101 行
- 进入 95 行直接打印 6 , 进入第 96 行根据结论二将 7 加入到宏任务队列中
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1 3 -1 5 4 6
微任务队列: 阻塞代码 12
宏任务队列: 11 13 2 7
阻塞代码: 第 98 行 到 第 101 行
- 进入第 98 行直接打印 8 , 进入第 99 行执行 getP 函数直接打印 -1 , 进入第 100 行将 9 加入到微任务队列
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1 3 -1 5 4 6 8 -1
微任务队列: 阻塞代码 12 9
宏任务队列: 11 13 2 7
阻塞代码: 第 98 行 到 第 101 行
- 进入第 101 行直接打印 10 , 此时堵塞代码中的 看起来像同步任务 的代码已经完成 , 根据结论二 , 需要继续完成堵塞代码中的微任务 , 所以退回第 100 行将微任务队列中的 9 提前打印为 9
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1 3 -1 5 4 6 8 -1 10 9
微任务队列: 12
宏任务队列: 11 13 2 7
阻塞代码:
- 堵塞代码处理完毕 , 继续执行微任务队列 , 直接打印 12
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1 3 -1 5 4 6 8 -1 10 9 12
微任务队列:
宏任务队列: 11 13 2 7
阻塞代码:
- 微任务队列处理完毕 , 开始执行宏任务队列 , 直接打印 11 13 2 7
此时 , 以下没有就是空
打印: 0 -1 ‘同步代码最后一句’ 1 -1 3 -1 5 4 6 8 -1 10 9 12 11 13 2 7
微任务队列:
宏任务队列:
阻塞代码:
- 执行结束 , 打印结果为 0 -1 ‘同步代码最后一句’ 1 -1 3 -1 5 4 6 8 -1 10 9 12 11 13 2 7
好了 , 我们再回顾一次得出的结论
- 遇到 await 时 , 可以视为将此 await 所在作用域内 await 下方的代码整块全部堵塞 , 堵塞可以视为塞入微任务队列中
- 堵塞的代码中包括的 .then 之内和之后的两部分 , 必须要等待 .then 之内的代码执行完成后 , 才能执行 .then 之后的代码 , 必须要等待 .then 之后的代码执行完成后 , 才能执行堵塞代码所在函数的下一行代码 , 其中需要等待的包括同步任务和微任务 , 而宏任务则统一加入到宏任务队列中
注意 : 对于 await.then 中的嵌套 async 和 await 同样满足上述两条结论 , 而对于 await.then 中的非 await 请求 , 则按照 await.then 中的正常情况处理
不使用 await
在 代码一 的基础上我们这次不使用 await 进行修饰 , 所以请看以下代码
代码二
我们做的修改仅仅是将 testP 函数中的 async 和 await 删掉了 , 保留开始的 async 是为了能返回一个 promise 对象
// 打印一个 -1 , 然后返回一个 promise 对象并执行成功回调
function getP() {console.log('-1')return new Promise((resolve, reject) => {resolve(1)})
}
// 创立一个定时器 , 并且马上打印输入的参数
function timer(a) {setTimeout(() => {console.log(a)}, 1);
}
// 声明一个函数 , 主要就是调用这个方法
async function testP() {console.log('0')getP().then(() => {console.log('1')timer('2')getP().then(res => {console.log('3')getP().then(() => console.log('4'))console.log('5')})console.log('6')timer('7')})console.log('8')getP().then(() => console.log('9'))console.log('10')
}
// 声明我们要使用的函数 , 其中调用了上述所有的方法
function test() {timer('11')testP().then(() => {console.log('12')})timer('13')console.log('同步代码最后一句')
}
// 使用函数
test()
我们先来看看执行结果是什么
这个其实很简单的了 , 里面可能让人纠结的一点就是微任务队列中再次出现微任务时 , 新的微任务放在哪里 , 答案就是新的微任务放在旧的微任务队列中的最后面 , 这就是为什么执行顺序是 3 会在 12 的后面而不是在 9 的前面
结论
- 遇到 await 时 , 可以视为将此 await 所在作用域内 await 下方的代码整块全部堵塞 , 堵塞可以视为塞入微任务队列中
- 堵塞的代码中包括的 .then 之内和之后的两部分 , 必须要等待 .then 之内的代码执行完成后 , 才能执行 .then 之后的代码 , 必须要等待 .then 之后的代码执行完成后 , 才能执行堵塞代码所在函数的下一行代码 , 其中需要等待的包括同步任务和微任务 , 而宏任务则统一加入到宏任务队列中
注意 : 对于 await.then 中的嵌套 async 和 await 同样满足上述两条结论 , 而对于 await.then 中的非 await 请求 , 则按照 await.then 中的正常情况处理
结束
其实写的比较复杂 , 而且结论我也不敢保证肯定对 , 但是目前就是这样用着
其实你完全不用在乎这些 , 因为除了面试题以外也很少会让你写这样的语句 , 而且你多半也不会这样写
有什么问题赶紧发评论留言大家一起讨论讨论啊
你可以复制下面的 HTML 代码在浏览器的控制台中进行测试
文件代码复制测试
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>异步</title><style>button {padding: 10px;}</style>
</head><body><button onclick="queryPromise()">queryPromise</button><pre>async function queryPromise() {let obj1let obj2obj1 = await getPromise()obj2 = await getPromise(obj1.id)console.log('obj1', obj1)console.log('obj2', obj2)} function getPromise(id = 20) {return new Promise((resolve, reject) => {let objif (id == 20) {obj = {id: 12,name: '张三'}} else if (id == 12) {obj = {id: 20,name: '邵雅虎'}} else {obj = {id: -1,name: '查无此人'}}resolve(obj)})}</pre><hr><button onclick="queryP()">queryP</button><pre>async function queryP() {await getP()console.log(1)timer(2)getP().then(() => {timer(4)console.log(3)})console.log(5)timer(6)return new Promise((resolve, reject) => {resolve('结束')})}function getP() {console.log('-1')return new Promise((resolve, reject) => {resolve(1)})}function timer(a) {setTimeout(() => {console.log(a)}, 1);}</pre><hr><button onclick="test()">test</button><pre>function getP() {console.log('-1')return new Promise((resolve, reject) => {resolve(1)})}function timer(a) {setTimeout(() => {console.log(a)}, 1);}async function testP() {console.log('0')await getP().then(async () => {console.log('1')timer('2')await getP().then(res => {console.log('3')getP().then(() => console.log('4'))console.log('5')})console.log('6')timer('7')})console.log('8')getP().then(() => console.log('9'))console.log('10')}function test() {timer('11')testP().then(() => {console.log('12')})timer('13')console.log('同步代码最后一句')}</pre>
</body>
</html>
<script>async function queryPromise() {let obj1let obj2obj1 = await getPromise()obj2 = await getPromise(obj1.id)console.log('obj1', obj1)console.log('obj2', obj2)}function getPromise(id = 20) {return new Promise((resolve, reject) => {let objif (id == 20) {obj = {id: 12,name: '张三'}} else if (id == 12) {obj = {id: 20,name: '邵雅虎'}} else {obj = {id: -1,name: '查无此人'}}resolve(obj)})}async function queryP() {await getP()console.log(1)timer(2)getP().then(() => {timer(4)console.log(3)})console.log(5)timer(6)return new Promise((resolve, reject) => {resolve('结束')})}function getP() {console.log('-1')return new Promise((resolve, reject) => {resolve(1)})}function timer(a) {setTimeout(() => {console.log(a)}, 1);}async function testP() {console.log('0')await getP().then(async () => {console.log('1')timer('2')await getP().then(res => {console.log('3')getP().then(() => console.log('4'))console.log('5')})console.log('6')timer('7')})console.log('8')getP().then(() => console.log('9'))console.log('10')}function test() {timer('11')testP().then(() => {console.log('12')})timer('13')console.log('同步代码最后一句')}
</script>
相关文章:

async和await用法理解和快速上手 , 同步任务和异步任务顺序安排和轻松理解 , js代码执行顺序表面知道
学习关键语句 : async , await 用法 await 怎么使用 同步任务和异步任务 微任务和宏任务 js中代码执行顺序 写在前面 虽然说 async 和 await 是 Promise 的语法糖 , 但是用惯了Promise 的人(我) , 还真不能超快速使用上这个语法糖 , 所以赶紧写一篇文章出来让各位了解了解这个…...

Linux下java服务占用cpu过高如何处理
Linux下java服务占用cpu过高如何处理 top命令查看进程信息 top按下shiftp,按cpu使用率排行,可见进程1932占用最高,并且是一个java服务 使用jps命令确认java服务 [rootVM-16-16-centos ~]# jps 1011 Jps 9462 yuan_back-0.0.1-SNAPSHOT.jar 1932 spigot-1.18.jar查找异常进程中…...

ros下用kinectv2运行orbslam2
目录 前提 创建工作空间 orbslam2源码配置、测试: 配置usb_cam ROS功能包 配置kinect 前提 vim 、 cmake 、 git 、 gcc 、 g 这些一般都装了 主要是Pangolin 、 OpenCV 、 Eigen的安装 18.04建议Pangolin0.5 创建工作空间 我们在主目录下创建一个catkin_…...

MVP简单模型搭建【架构】
MVP简介 MVP是一种项目架构设计模式(说白了就是我们产品的一种设计方案) 其实MVP本质 就是将View和Model完全隔离,通过Presenter统一调度管理(Presenter扮演着中介的角色)传统的设计思路是我们直接跟房东谈࿰…...

若依ruoyi框架实现目录树与查询页面联动
目录1、业务场景2、前端api.js修改index.vue修改template修改script修改3、后端controllerserviceimpldomainentitytreeselect1、业务场景 后管页面实现目录数与查询页面的联动,类似若依框架用户管理页面。 2、前端 api.js修改 在原有的js文件里配置目录树的查…...

Laravel框架学习笔记——Laravel环境配置及安装(Ubuntu20.04为例)
目录引言1、安装Nginx2、安装PHP3、安装Composer4、搭建Laravel框架项目5、修改Nginx映射6、安装MySQL引言 好久没写博客了,因为个人需要, 所以要涉及到Laravel框架的学习,所以会出一系列的关于PHP的Laravel框架学习笔记,希望能够…...

模拟百度翻译-课后程序(JAVA基础案例教程-黑马程序员编著-第六章-课后作业)
【案例6-5】 模拟百度翻译 【案例介绍】 1.任务描述 大家对百度翻译并不陌生,本案例要求编写一个程序模拟百度翻译。用户输入英文之后搜索程序中对应的中文,如果搜索到对应的中文就输出搜索结果,反之给出提示。本案例要求使用Map集合实现英…...

自然语言处理(NLP)之求近义词和类比词<MXNet中GloVe和FastText的模型使用>
这节主要就是熟悉MXNet框架中的两种模型:GloVe和FastText的模型(词嵌入名称),每个模型下面有很多不同的词向量,这些基本都来自wiki维基百科和twitter推特这些子集预训练得到的。我们只需要导入mxnet.contrib中的text模块即可,这里…...
2023年CDGA考试-第13章-数据质量(含答案)
2023年CDGA考试-第13章-数据质量(含答案) 单选题 1.在导致数据质量问题的常见原因中关于数据输入问题以下描述正确的是: A.数据采集端缺乏数据质量管控 B.相同字段重复设计导致数据不一致 C.缺乏数据采集规范的制定 D.所有描述都正确 答案 D 2.数据质量计划应将其范围限…...

ASEMI高压MOS管ASE65R330参数,ASE65R330图片
编辑-Z ASEMI高压MOS管ASE65R330参数: 型号:ASE65R330 漏极-源极电压(VDS):650V 栅源电压(VGS):20V 漏极电流(ID):12.5A 功耗(P…...
LeetCode动态规划经典题目(九):子序列、子数组问题
目录 31. LeetCode674. 最长连续递增序列 32. LeetCode18. 最长重复子数组 33. LeetCode1143. 最长公共子序列 34. LeetCode1035. 不相交的线 35. LeetCode53. 最大子数组和 36. LeetCode392.判断子序列 37. LeetCode115. 不同的子序列 38. LeetCode583. 两个字符串的删…...

如何利用有限的数据发表更多的SCI论文?——利用ArcGIS探究环境和生态因子对水体、土壤和大气污染物的影响
SCI的写作和发表是科研人提升自身实力和实现自己价值的必要途径。“如何利用有限的数据发表更多的SCI论文?”是我们需要解决的关键问题。软件应用只是过程和手段,理解事件之间的内在逻辑和寻找事物之间的内在规律才是目的。如何利用有限的数据发表更多的…...

六【 SpringMVC框架】
一 SpringMVC框架 目录一 SpringMVC框架1.什么是MVC2.SpringMVC概述3.SpringMVC常见开发方式4.SpringMVC执行流程5.SpringMVC核心组件介绍6.快速构建Spring MVC程序✅作者简介:Java-小白后端开发者 🥭公认外号:球场上的黑曼巴 🍎个…...

【BBuf的CUDA笔记】八,对比学习OneFlow 和 FasterTransformer 的 Softmax Cuda实现
0x1. OneFlow/FasterTransformer SoftMax CUDA Kernel 实现学习 这篇文章主要学习了oneflow的softmax kernel实现以及Faster Transformer softmax kernel的实现,并以个人的角度分别解析了原理和代码实现,最后对性能做一个对比方便大家直观的感受到onefl…...
python 类对象的析构释放代码演示
文章目录一、类的构造函数与析构函数二、代码演示1. 引用的更迭2. 只在函数内部的类对象三、函数内部返回的类对象1. 使用全局变量 引用 函数内部的类对象一、类的构造函数与析构函数 init 函数是python 类的构造函数,在创建一个类对象的时候,就会自动调…...

Hadoop Shell常用命令
Hadoop Shell命令在管理HDFS的时候还是比较常用的,Hadoop Shell命令与shell命令极为相似,但是方便查询,在这里总结分享,大家enjoy~~ 1,cat 语法格式:hadoop fs -cat URI [URI …] 含义:将路径…...

Android中级——色彩处理和图像处理
色彩处理 通过色彩矩阵处理 色彩矩阵介绍 图像的RGBA可拆分为一个4行5列的矩阵和5行1列矩阵相乘 其中4行5列矩阵即为ColorMatrix,可通过调整ColorMatrix间接调整RGBA 第一行 abcde 决定新的 R第二行 fghij 决定新的 G第三行 klmno 决定新的 G第四行 pqrst 决定新…...

C++类和对象:类的定义、类对象的存储、this指针
目录 一. 对于面向过程和面向对象的认识 二. 类 2.1 struct关键字定义类 2.1.1 C语言中的struct关键字 2.1.2 C中的struct关键字 2.2 class关键字 2.1 使用class关键字定义类 三. 类的访问限定及封装 3.1 类的访问权限及访问限定符 3.1.1 访问权限 3.1.2 访问限定…...

代码随想录算法训练营第三十九天 | 62.不同路径,63. 不同路径 II
一、参考资料不同路径https://programmercarl.com/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84.html 视频讲解:https://www.bilibili.com/video/BV1ve4y1x7Eu不同路径 IIhttps://programmercarl.com/0063.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84II.htmlhttps://progr…...
数据库复习3
一. 简答题(共1题,100分) 1. (简答题) 存在数据库test,数据库中有如下表: 1.学生表 Student(Sno,Sname,Sage,Ssex) --Sno 学号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 主键Sno 2.教师表 Teacher(Tno,Tname) --T…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...