跳转到内容
彼岸论坛

小天管理

管理员
  • 内容数

    15357
  • 注册日期

  • 最后上线

  • 得奖次数

    1

小天管理 发表的所有内容

  1. 新崑崙,这座由外星种族太阳人所建造的庇护所数百年间沉静如海。在这片广褒的疆域裡,神祇们为凡人留下一处被称为桃花村的应许之地, 亘古以来居住于此的人们持续着古老的祭祀,神圣的仪式会庇佑其子民免于种种灾厄。很快地,又一次的祭典即将举行,村裡的人们正忙着张罗各类祭品。然而就在一切如常之时,一位被遗忘的英雄,羿,从漫长的沉睡中意外甦醒,并在道的洪流掀起巨大涟漪。 跟随羿的脚步,一起在復仇的路上前行并击败统治新崑崙的九王。探索这个道教庞克的世界解开新崑崙神秘的面纱。 类隻狼的战斗: 攻击与格档快速的不停交互切换的战斗节奏。利用格挡后所累积的能量,冲向敌人利用灌满『气』的符咒将敌人引爆。 结合空中冲刺、二段跳、攀牆等传统2D平台动作游戏的操作交织出节奏明快的平台战斗。 紧张刺激的魔王战: 准备好面对危险的古老统治者、凶残的变种外星生物。利用你所有的工具和技能挑战这些令人生却的恐怖敌人。 道教庞克的世界设定: 道教结合赛博庞克的世界设定!将科幻元素与东方传说以及道教神话与哲学产生全新的道教庞克! 世界探索: 探索新崑崙这个每个区域都有不同特色环境建筑,交通干道互相连通的世界。 关卡中藏有秘密和宝藏等待玩家挖掘与探索。但同时路途上也佈满陷阱和敌人,想要拿到报酬必须涉险而入。 NPC与支线任务: 在旅途中,与不同的NPC互动可获得稀缺物资和进行装备升级。在这个充满威胁的世界, 善用一切人脉与资源将会是击败九王的重要关键。另外,完成支线任务,除了优渥的报酬外,对剧情推进也有极大益处。 日漫手绘风格: 九日中有着许多精緻手绘背景、动画和漫画,製作时我们借镜了许多日本动画与漫画, 希望用大量的逐格绘製以展现这款游戏的视觉特色。在各种细节上,包括过场动画和头目战,团队花费了极大精力企图建构出令人惊艳的画面。 链接: https://pan.baidu.com/s/1dqUHPLhQbCOMKQRXTxOMjQ 提取码: rgzj 解压密码:laoquzhang.com
  2. 雾锁王国 Enshrouded 你是火焰之子,一个濒死种族最后的希望火苗。苏醒吧,克服腐化一切的迷雾所裹挟的恐怖, 重新夺回你的王国所失落的瑰丽。置身于广袤世界,战胜难以想象的强大Boss,修造宏伟厅堂, 在这款至多16名玩家的合作类生存动作RPG中开辟属于自己的道路。 薪谷王国已经陷入沉沦。出于对魔法力量的贪念,你的祖先们释放了一种吞噬世界的疫病。 《Enshrouded》融合了生存、制作以及动作RPG战斗,游戏背景设定在了一个基于体素构筑的辽阔大陆。无论是攀登山脉还是跨越沙漠,你将可以在这个开放世界中自由选择前进的方向并塑造自己的命运。 点燃火焰的远古力量,通过一段段残缺的故事拼凑出表面之下的真相。 在迷雾中求得生存 游戏一开始,你唯一拥有的就是战胜荒野的不屈意志。在失落王国的遗迹中搜寻宝贵物资,竭尽所能击退意欲将你吞噬的凶猛野兽。 穿越森林、洞穴与地牢,寻找隐秘的知识与宝藏。不断积累力量并最终深入迷雾,对抗来自深渊的可怕存在。 激动人心的战斗 吞噬一切的迷雾将腐化被触及的所有存在,不断扭曲与操纵身处其中的万物生灵。披荆斩棘,战胜残忍的派系与可怕的Boss,对抗森林中的恶鬼,洞穴中的Vukah以及迷雾中的恐惧生物。 闪躲、招架并埋伏你的敌人,运用意想不到的战技与强力法术。学会利用敌人的弱点,利用深入复杂的技能树系统培养出只属于你的独特游玩风格。 打造史诗配置 重新唤醒大地的生命力!基于体素的建造系统将最大程度释放你的创造力,打造超乎想象的壮观建筑,随心所欲挑选琳琅满目的建筑材料与家具。但是在建造的过程中不要仅仅为自己考虑,游戏中的NPC角色将会向你寻求庇护,他们将为你解锁高级工坊以及打造史诗武器与护甲的能力。 铸就传奇装备 打造并定制让人眼花缭乱的各类传奇武器与护甲,获取横扫千军的伟力。只有精通盾牌、刀剑、法杖与弓箭,你才能够抵挡住迷雾的无情推进。 呼朋唤友 与好友们一同体验16名玩家的多人合作游戏。合理分配各自的身份并考虑技能互补,齐心协力斩妖除魔、收集宝藏并战胜肆虐大地的怪物。 解开陨落王国的秘密 穿越薪谷的世界,从神秘的烬土沙漠到喧嚣森林的幽邃荫庇,领略栩栩如生的陨落文明与远古谜团。 在迷雾深处,一个失落王国的遗迹之下埋藏着常人难以想象的故事,魔法、废墟、希望与救赎都在等待被发掘。 链接: https://pan.baidu.com/s/1IzwGvusKzZWCnFCQU-kMNQ 提取码: dtcu 注意:通过“steamclient_loader.exe”启动游戏 解压密码:laoquzhang.com
  3. 虚拟无限计划 Virtua Unlimited Project 当「虚拟主播」化身被称为「经营者」的超能力者, 在「虚拟」的游戏世界中异想幻斗, 一场属于「虚拟主播」的华丽演出就此拉开序幕…… 《Virtua Unlimited Project 虚拟无限计划》是一款以「虚拟主播」为主题元素的2D横版像素风动作游戏。形形色色在网络空间中活跃着的虚拟主播们将参演其中,构造属于虚拟主播的主题世界。玩家将扮演虚拟主播「相沢加奈」,在这个名为「NEO巴比伦」的世界中,与化身成超能力者的各路虚拟主播们相遇,她们将以熟悉的相貌出现,又以稍显陌生的超能力向各位发出挑战,可千万不要掉以轻心。 游戏核心玩法参考GBA经典ACT作品「Z系洛O人」,以传统平台跳跃玩法,复古动作系统设计,再现属于那个年代的硬核战斗体验。此外,游戏也将引入更具「角色扮演」属性的玩法内容,在激烈战斗之余,让每一位出现在作品中的虚拟主播都能展现出独特魅力。 2XXX年,世界上最大的量子计算机「巴比伦」做出了预告。 人类将在100年内灭亡。 亨格斯·利德雷博士提出了能够拯救所有人的「新世界计划」。 让所有人进入冬眠舱休眠,再使用纳米机器人恢复地球的生态平衡。 醒来后,人们就能在重生的世界里开始新的生活。 随着计划的成功实施,新世界中出现了两种新事物。 新型能量「存在支持度」通称E.S.P。 新型天灾「暴乱污染灾害」通称暴乱事件。 暴乱事件是一种难以预测的突发性自然灾害。 通常表现为在一定范围内不断生成「暴乱体」对周边进行无差别攻击。 不断的清除暴乱体直至暴乱污染完全消失是人类掌握的对抗暴乱的唯一方法。 E.S.P是一种从人与人之间的联系中产生的新能量。 人类能够使用现有技术方便的将E.S.P转换为各种能源。 对E.S.P的运用大大减轻了人类对抗暴乱的负担。 人类中有着能够不借助外力直接使用E.S.P的存在。 他们能凭借E.S.P展现种种超越常理的力量,奋战于对抗暴乱的第一线。 他们能使用E.S.P广泛的参与到世界的建设,活跃在各个领域的最前沿。 他们被称为——「经营者」 「NEO巴比伦」政府也构建完善了以E.S.P为基础的新社会体系。 随着NEO巴比伦政府成立50周年和平庆典到来。 某种无法预测的暗流似乎在这个和平的世界里开始涌动了…… 通过与关卡中的「经营者」Boss交战,战胜后能够获取Boss的部分能力与属性。并且领悟其招牌技能,开发习得角色自身的「EX技能」。 「经营者」Boss的属性能力间存在克制关系,如何利用好将是克敌制胜的关键。 一阵”友好交流”后,Boss会加入己方。角色在攻关流程中能够施展出召唤Boss助阵的「援护技能」。 游戏加入了以「极速飞踢」为特色的动作体系。该动作不仅能够用来与场景或者敌人互动,在飞踢击中目标弹起后还会使角色获得短暂的无敌时间。与其他特殊动作间可进行相互取消,拥有极高的可玩性与无限的开发潜力! 在游戏的关卡中隐藏着诸如「冰面防滑」,「快速蓄力」,「自动蓄力」,「自动回复」等能够为角色提供各式各样特殊能力的「扩展程序」,请积极探索关卡的犄角旮旯吧。 「扩展程序」的安装并非没有限制,请留意「扩展程内存占用」RAM。超载安装会受到被击伤害增加的惩罚,且超的越多,罚得越多。 链接: https://pan.baidu.com/s/1RgX-h694maUR3Lq_0kjXRA 提取码: pwh7 解压密码:laoquzhang.com
  4. 《活侠传》是一款PC角色扮演类单机游戏。 玩家所扮演的是一名资质凡庸,且不受人待见的唐门杂鱼,没有主角光环,人生难度EX-HARD。 江湖动荡,不可一世的唐门已然式微,从前得罪的仇家却前仆后继攻打过来,身为一名喽啰,是该独善其身,还是献身为门派存亡奉献一己之力? 细腻的人格特质参数将随玩家决策随时变动,无法预知的随机事件会导致剧情展开分秒失控。 人在江湖身不由己,好坏都能是一个精彩绝伦的故事,你的故事。 人在江湖,身不由己。你有时候能做出选择,有时候会被无情的命运玩弄。 剧情展开分秒失控,你大可尽力挣扎,但你永远逆料不到,老天明天会想出什么新奇花招蹂躏你。 玩家可以透过炼丹房钻研毒术、锻冶场锻造暗器,卖命打杂争取师长好感,改变门派的政策,想尽办法壮大家园,迈向胜利! 主角的人格特质将随着玩家的决策、行动或天命而变动,从而影响人际关系、剧情走向,以及决斗策略! 战术将依据人格特质而丰富多变。 从秘籍中领会的技能越多,你的战术就越灵活!料敌机先,在决斗中获得胜利吧! 弹幕与闪避!不讲武德的门派厮杀。又不是超能力者,武功再高也抵不过千军万马,与其逞英雄,还不如想方设法保存小命。 链接: https://pan.baidu.com/s/1Myw2qiZtloUai5__JWcDSg 提取码: 3sgn 解压密码:laoquzhang.com
  5. 有什么敏感词不能说清楚吗? 这是我要发的东西,没看出那里戳到 G 点了 各位彦祖,求推荐 3000 左右海绵坐垫的人体工学椅 海绵坐垫是硬要求(保友金豪 E2 把我腿干麻了),3000 左右,腰部支撑好一点的(之前的冈村 Sylphy Light 坐着是舒服,但腰部可以说是毫无支撑),彦祖们推荐一波,多谢 另外还是求一波推荐
  6. 我想只用苹果键盘,目的是想同时记忆 mac 和 windows ,切换系统时键盘也能跟着连上相应系统,而并不需要同时控制两个系统。(也就是用 A 系统时 B 系统是休眠状态的) 要求: 1.两个系统都通过无线连接( mac 蓝牙 win 有线那种不想) 2.无论通过软件还是硬件,只要能实现就可以(比如有没有一种叫蓝牙中继之类的?)
  7. 需求: 个人网站服务器(至少是 CDN )在中国大陆,以避免各种玄学访问问题 平时保证基本的境内访问速度体验(支持境外、Websocket 、IPv6 更优) 自动防止 DDCC 造成高额账单,防范措施的成本尽可能低 已知: 对于主流云服务,个人用户承受能力范围内的大多是超低带宽服务器,难以满足需求。因此往往采用 CDN 、对象存储等服务,面对终端用户的基本都是 CDN 。虽然 CDN 不太可能被打垮,但攻击者可以耗尽站长的钱包以实现拒绝服务。即使流量相对更便宜,仍能产生巨量账单。此前 V2EX 、hostloc 等社区已经有不少讨论,阿里云、腾讯云等服务商也有高额账单风险建议。但对于个人网站,当前的措施似乎仍然存在隐患: 防盗链、鉴权:恶意攻击者指定 Referer 没有难度。一般也不可能所有页面内资源都上鉴权,只要逮住一个刷就可以制造大量流量。 WAF 、DDoS 防护:查过的几个大厂价格基本不属于个人用户的范畴。 黑白名单:只能事后补救,难以事前预防。 单请求限速:只能防最基础的小白,多请求、多节点就不好说了。 带宽 or 流量封顶:个人认为还算有点用。但是厂商通常会指出监控数据存在一定延迟,下线前产生的流量、带宽、请求数等资源消耗将会正常计费。(顺便一提,部分产品没有这个功能,例如阿里 DCDN 仅支持 10Gbps 级别的带宽限速,没有封顶选项) 问题: 对于主流大厂,使用 CDN 带宽封顶似乎是一个暂且能用的方案(尤其是腾讯、华为等,在配置界面直接支持 5 分钟级流量封顶、百分比告警、自动解封)。但这么做是否真能保住钱包?不知道是否有案例分享。 另外,其它国内厂商是否会提供更好的解决方案?像 Cloudflare 这样能硬抗的“大善人”肯定不能指望,但我至少会希望: 有 CDN 方案支持达量限速,或者至少承诺余额用完不会倒扣钱。 跳出 CDN 的方案,服务器带宽够大也行,流量用完限速或停机。 如果有,欢迎推荐。或者其它能解决问题的方案也欢迎讨论。 注:网站自身成本<50 CNY/月,如果云原生且没什么人访问甚至可以<10 CNY/月,考虑防范措施后希望<100 CNY/月。
  8. FullHD 的电视都用了小 20 年了,直播的视频规格还在 1080i ,25Hz 的规格,啥时候能上 4K60Hz 啊,至少先 60Hz 也好啊!!
  9. 特别是电脑屏幕,一定要调到最亮才觉得能看清,亮度降 3-5 个等级就觉得屏幕很模糊。 前段时间出现过看手机屏幕电脑屏幕就会头晕,缓了一周好了些。现在手机不调到最亮没法看,总感觉自看不清,是只我一个还是都这样? 电脑 MAC AIR ,手机 MEIZU20 C 还是上了年纪?不应该吧我 30 都不到。
  10. 2024 ,0611-0616 ,第 24 周 坚持了 162 天后,终于破戒了,点了外卖。点的是健康沙拉餐,吃完后第二天还真就掉秤了。 本周开发 国内安卓市场 这周国内四个安卓市场( HMOV )都同步更新了极简日记和极简便签,更新内容只有一点:加入备案信息的显示。 之前收到了小米的通知,必须在 App 中加入备案号的显示,还提供了规范文档。我没留意其他几个市场是否有同样的要求,索性就一起更新了。按照国内安卓市场的尿性,都是一丘之貉,早晚的事。 极简时钟新版本一切就绪,但是一想到要操作后端和数据库就心生胆怯,于是拖延症就又犯了。 极简时钟 App Store iOS 版的新表盘还在开发中,一言难尽,进度不理想。 Google Play Google Play Console 终于又开放了 TestFlight ,这下可以在手机上看到各种数据了,就不用跑到电脑上看了。 没想到上周的下载量并没有触底反弹,反而还在下降,这周差一点跌破了 700 。 上周开始的两个实验都没有看出来任何效果。商品详情实验,因为下载量很低,所以也看不出来两版截图的优劣。价格实验,因为针对的 10 个国家都几乎没有付费,所以也看不出来区别。 WWDC24 没看直播,周二早上醒来后看了眼各种群内的讨论,感觉这一届 WWDC 带来的惊喜并不多。 作为重头戏的 Apple Intelligence 目前还不能体验,而开发者非常关心的 Xcode16 的代码补全功能,需要满足四个条件才能使用到: macOS 15 16G 内存以上 Apple Silicon 非大陆的 Mac 是的,大陆的开发者都不能使用,这次锁的是机器,我们又因为各种各样的原因被特殊对待了。不过呢,在看了国外开发者分享的视频后,目前 Xcode16 的代码补全功能非常孱弱,比起其他 Copilot 差得太多太多了。心理又好受了一丢丢。 对于这届 WWDC 我比较失望,不仅发布的各种新特性没什么精彩之处,剩下的大部分还都是期货,就连官方看 WWDC Session 的 Developer 也出问题了,必须改成英文才能刷出来最新的视频,之前我一直用中文,就奇怪为什么一直没有新视频。Developer 改成英文后,就没有了中文字幕,再加上加载速度慢,还不如在 YouTube 上看 Apple 自己上传的视频,加载又快又清晰还有中文字幕。 我对这次 WWDC24 的兴奋点比起之前低很多,这一周只看了五六个 Session ,都是关于 SwiftUI 和 Xcode 的,除了几个需要跟进适配的功能,目前也没发掘出什么可以值得做的 idea 。 新尝试 之前看 WWDC 的 Session 后大部分的新特性都会忘掉,因为只是走马看花地看一遍,并没有亲手敲代码。这一年决定把自己感兴的新 API 都写一遍,最先写的就是今年新推出的 Zoom Transition 。代码很简单,写完了就冒出个念头,录个 demo 视频上传到 Youtube 岂不更好,正愁频道里没有新内容呢。平时也总看别人的代码示例视频,自己也就尝试做了一个。 本来是想用 QuickTime Player 录屏,但是群友更推荐 OBS ,研究了一下,确实不错。尽管不是直播,但是录的时候还是状况频出,总感觉有人在看似的,居然有些紧张。比起平时写代码,更多出现了拼写错误和 API 拼写错误。全程我没有讲话,就是纯录屏,录完了把出错的地方都剪掉,添加个片头和片尾就直接提交了。 由于是第一次录这种视频,发现了很多需要改进的地方: 字体要大一些,不能用平时写代码的字体大小 想解释的东西都靠注释写在了 Xcode 中,这里或许用剪辑软件添加额外的说明文字更好 视频的各种元数据还需要多向同类视频学习
  11. 我目前用法感觉有限,只用来:跑 docker 部署一些本地开发依赖的服务,比如 redis ,数据库之类。 本来想用来多实例部署 k8s 集群之类,发现多实例之间网络是共享的,没有隔离。所以该用虚拟机的时候还是得老老实实虚拟机。 另外跨文件系统 IO 速度简直了。 大家都有什么用法?
  12. sourcetree 平时好好的,不知道是什么操作触发了内存溢出还是啥。现在操作什么东西都直接应用未响应。 请问这个情况大家有遇到过嘛,windows 上其他 gui ,比如腾讯新出的 ugit 好用嘛,看到功能好像是游戏开发者相关用的更多。
  13. vaultwarden 用了几年,备份方案翻来覆去折腾了好多种,这次利用 nginx syslog 实现“精确”的备份: log_format json-log escape=json '{"status":$status,"request_method":"$request_method","request_uri":"$request_uri"}'; server { location / { # ... proxy_redirect off; proxy_pass http://vaultwarden; proxy_http_version 1.1; access_log syslog:server=syslog-server:50333,facility=local7,tag=nginx,severity=info,nohostname json-log; } } 这样 syslog-server:50333 就可以收到完成的请求,可以拿到 status request_method request_uri 等信息,如此只需要实现个简单的 syslog server ,便可以根据这些信息来决定是否调用备份:例如所有 GET 请求都无需关心,因为对数据库没有更改;例如我不关心登录、注册、设备、二次验证之类的变更,则 ^/identity/accounts/prelogin ^/identity/connect/token .*/devices/.* .*/two-factor/.* 等请求也可以略过;例如我不使用 sends ,.*/sends/.* 也可以忽略。 bitwarden 客户端让每一次更改都必须对应 vaultwarden 数据库的更改,这个备份方案理论上也可以确保对自己有价值的变更都被备份。 部署运行了一周,我很喜欢这个方案 诸位觉得如何
  14. 软件工程专业,25 年本科毕业 目前专升本在读,按理来说应该今年年底去参加考研,但无奈学校事情太多没有时间学习(就算硬学我会觉得自己可支配学习时间没有别人多而留下遗憾),所以我在想明年在外实习+上班,边工作边准备考研的可行性怎么样?今年同时在学学校的课和学习日语,有对日开发的想法。个人情况是对计算机的学习很有热情,学习能力比普通同学强。没有转专业的想法。主要在学习 java ,前端了解 vue ,了解了很多东西 lua kotlin gamemaker 但都不深入并没有继续学下去。 想从 [技术学习路线] 和 [生涯规划] 两个方面请教身为过来人的大佬们的建议,这一年内我该怎么做,努力学日语 还是为找工作做准备 还是混个小公司考研?
  15. 本人是做 WebRTC 音视频聊天开发,音视频走的都是 UDP 协议。在模拟环境对比腾讯会议和微信,我们做的程序在抗丢包,带宽拥塞控制方面都不比腾讯差多少。 但是在线上环境总有不少用户反馈,使用我们的产品视频通话就卡,使用腾讯会议就没问题。通过统计数据看,用户卡的时候,UDP 通信带宽非常低,基本在 100kbps 以下了。 最近看了 V 站上有讨论国内运营商对 UDP 有限制,所以想弄明白,运营商事对国外到国内的 UDP 有限制,还是境内内部的 UDP 也有限制。为什么相同条件下腾讯会议表现不卡,我们的卡?难道运营商对腾讯会议这些用户量大的软件有白名单?
  16. 最近在找一个简单的 C++11 线程池实现,发现网上有很多相关的代码,在 CSDN 网上看到一个比较简洁的。但是总感觉是不是实现错了。 Any 类 noncopyable 的,仅仅支持移动语义, Result 类使用了 Any 实例作为成员变量,那么 Result 类应该也是 noncopyable 的, Result SubmitTask(std::shared_ptr<Task> taskPtr);直接使用了复制语义,应该是有问题吧,可是代码能够被 vs2022 正常编译。 threadpool.h #pragma once #include <vector> #include <cstdint> #include <queue> #include <memory> #include <atomic> #include <mutex> #include <thread> #include <condition_variable> #include <functional> #include <sstream> #include <unordered_map> // Any 类型:可以接收任意数据的类型 // 任意其他类型 template // 能让一个类型指向其他类型,基类指针可以指向子类 class Any { public: Any() = default; ~Any() = default; Any(const Any&) = delete; Any& operator=(const Any&) = delete; Any(Any&&) = default; Any& operator=(Any&&) = default; template<typename T> Any(T data) : m_base(std::make_unique<Derive<T>>(data)) {} template<typename T> T cast_() { Derive<T>* pd = dynamic_cast<Derive<T>*>(m_base.get()); if (pd == nullptr) { throw "type is unmath!!"; } return pd->m_data; } private: // 基类 class Base { public: virtual ~Base() = default; }; // 派生类 template<typename T> class Derive : public Base { public: Derive(T data) : m_data(data) {} public: T m_data; }; private: std::unique_ptr<Base> m_base; }; // 实现一个信号量类 class Semaphore { public: Semaphore(int limit = 0) : m_resLimit(limit) {} ~Semaphore() = default; // 获取一个信号量资源 void wait() { std::unique_lock<std::mutex> lock(m_mtx); // 如果没有资源,阻塞线程 while (m_resLimit < 1) { m_cond.wait(lock); } m_resLimit--; } // 增加一个信号量资源 void post() { std::unique_lock<std::mutex> lock(m_mtx); m_resLimit++; m_cond.notify_all(); } private: int m_resLimit; // 资源量 std::mutex m_mtx; std::condition_variable m_cond; }; // Task 类型前置声明 class Task; // 实现接收提交到线程池的 task 任务执行完成后的返回值类型 class Result { public: Result(std::shared_ptr<Task> task, bool isValid = true); ~Result() = default; // setVal void setVal(Any result); // get 方法,用户调用这个方法获取 task 的返回值 Any get(); private: Any m_any; Semaphore m_sem; std::shared_ptr<Task> m_task; std::atomic_bool m_isValid; }; // 任务抽象基类 class Task { public: void exec(); void setResult(Result* res); virtual Any run() = 0; private: Result* m_result{ nullptr }; // 不要用智能指针,task 含有 Result Result 含有 task ,可能导致问题 }; class MyTask : public Task { public: MyTask(int start, int end) : m_start(start), m_end(end) {} Any run() { std::ostringstream ostr; ostr << std::this_thread::get_id(); printf("thead %s, task start \n", ostr.str().c_str()); uint64_t sum = 0; for (int i = m_start; i <= m_end; i++) { sum += i; } printf("sum %llu\n", sum); std::this_thread::sleep_for(std::chrono::seconds(2)); printf("thread %s, task finish \n", ostr.str().c_str()); return sum; } private: int m_start; int m_end; }; enum ThreadPoolMode { MODE_FIXED, // 固定数量的线程 MODE_CACHED, // 线程数量可以动态增长 }; class Thread { public: using ThreadFunc = std::function<void(int)>; Thread(ThreadFunc func); ~Thread(); void Start(); int GetId() { return m_threadId; } private: ThreadFunc m_func; static int generateId; int m_threadId; }; class ThreadPool { public: ThreadPool(); ~ThreadPool(); // 设置线程池工作模式 void SetMode(ThreadPoolMode mode); // 设置任务数量上限 void SetTaskQueMaxThreshold(int value); // 给线程池提交任务 Result SubmitTask(std::shared_ptr<Task> taskPtr); // 开启线程池 void Start(int initThreadSize = std::thread::hardware_concurrency()); private: ThreadPool(const ThreadPool&) = delete; ThreadPool& operator=(const ThreadPool&) = delete; // 定义线程函数 void ThreadFunc(int threadId); bool CheckRunningState() const; private: std::unordered_map<int, std::unique_ptr<Thread>> m_threadMap; // 线程列表 int m_initThreadSize; // 初始的线程数量 std::atomic_int m_curThreadSize; // 当前线程数量 std::queue<std::shared_ptr<Task>> m_taskQue; // 任务队列 std::atomic_int m_taskSize; // 任务的数量 int m_taskQueMaxThreshold; // 任务队列的数量上限 std::mutex m_taskQueMtx; // 保证任务队列的线程安全 std::condition_variable m_taskQueNotFullCv; // 表示任务队列不满 std::condition_variable m_taskQueNotEmptyCv; // 表示任务队列不空 std::condition_variable m_exitCv; // 退出线程池 ThreadPoolMode m_poolMode; // 当前线程池的工作模式 std::atomic_bool m_isPoolRuning; // 当前线程工作状态 }; threadpool.cpp #include "threadpool.h" #include <functional> #include <iostream> constexpr int TASK_MAX_THRESHOLD = 1024; ThreadPool::ThreadPool() : m_initThreadSize(4), m_taskSize(0), m_taskQueMaxThreshold(TASK_MAX_THRESHOLD), m_poolMode(ThreadPoolMode::MODE_FIXED) { } ThreadPool::~ThreadPool() { m_isPoolRuning = false; std::unique_lock<std::mutex> lock(m_taskQueMtx); // 线程 要么在阻塞中 要么在工作中 while (m_threadMap.size() > 0) { m_taskQueNotEmptyCv.notify_all(); // 唤醒等待的工作线程 m_exitCv.wait(lock); } } void ThreadPool::SetMode(ThreadPoolMode mode) { if (m_isPoolRuning) { return; } // 线程池启动后,不允许设置线程池一些参数 m_poolMode = mode; } void ThreadPool::SetTaskQueMaxThreshold(int value) { if (m_isPoolRuning) { return; } m_taskQueMaxThreshold = value; } Result ThreadPool::SubmitTask(std::shared_ptr<Task> taskPtr) { // 获取锁 std::unique_lock<std::mutex> lock(m_taskQueMtx); // 线程通信,检查任务队列是否有空余 while (m_taskQue.size() >= m_taskQueMaxThreshold) { // 用于提交任务,不能阻塞太长时间,如果超过 1s ,给用户返回提交失败 if (m_taskQueNotFullCv.wait_for(lock, std::chrono::seconds(1)) == std::cv_status::timeout) { return Result(taskPtr, false); } } // 如果有空余,把任务提交到任务队列中 m_taskQue.emplace(taskPtr); m_taskSize++; // 因为新放了任务,任务队列肯定不为空了,在 m_taskQueNotEmptyCv 进行通知,赶快分配线程执行这个任务 m_taskQueNotEmptyCv.notify_all(); return Result(taskPtr); } void ThreadPool::Start(int initThreadSize) { m_initThreadSize = initThreadSize; m_curThreadSize = initThreadSize; m_isPoolRuning = true; // 创建线程对象 for (int i = 0; i < m_initThreadSize; i++) { auto ptr = std::make_unique<Thread>(std::bind(&ThreadPool::ThreadFunc, this, std::placeholders::_1)); int threadId = ptr->GetId(); m_threadMap.emplace(threadId, std::move(ptr)); } // 启动所有线程 for (auto iter = m_threadMap.cbegin(); iter != m_threadMap.end(); iter++) { iter->second->Start(); } } void ThreadPool::ThreadFunc(int threadId) { while (true) { // 获取锁 std::unique_lock<std::mutex> lock(m_taskQueMtx); std::ostringstream ostr; ostr << std::this_thread::get_id(); printf("thead %s, To Get task \n", ostr.str().c_str()); // 判断任务队列是否为空 while (m_taskQue.empty()) { if (!m_isPoolRuning) { m_threadMap.erase(threadId); m_exitCv.notify_all(); printf("deconstructor thread exit, id = %d\n", threadId); return; } m_taskQueNotEmptyCv.wait(lock); } printf("thead %s, Getted task \n", ostr.str().c_str()); // 不为空,获取任务 auto taskPtr = m_taskQue.front(); // front()返回引用,auto 忽略引用属性,正好满足需要 m_taskQue.pop(); m_taskSize--; lock.unlock(); // 释放锁; // 如果任务队列还有任务,通知其他线程执行任务 if (m_taskQue.size() > 0) { m_taskQueNotEmptyCv.notify_all(); } // 通知队列已经不满 m_taskQueNotFullCv.notify_all(); taskPtr->exec(); if (!m_isPoolRuning) { m_threadMap.erase(threadId); m_exitCv.notify_all(); printf("deconstructor thread exit, id = %d\n", threadId); return; } } } bool ThreadPool::CheckRunningState() const { if (m_isPoolRuning) { return true; } return false; } // 线程方法 int Thread::generateId = 0; Thread::Thread(ThreadFunc func) : m_func(func), m_threadId(generateId++) { } Thread::~Thread() { } void Thread::Start() { std::thread t(m_func, m_threadId); t.detach(); } Result::Result(std::shared_ptr<Task> task, bool isValid) : m_task(task), m_isValid(isValid) { m_task->setResult(this); } void Result::setVal(Any result) { m_any = std::move(result); m_sem.post(); // 通知已经获得结果 } Any Result::get() { if (!m_isValid) { return ""; } m_sem.wait(); // 等待结果 return std::move(m_any); } void Task::exec() { if (m_result != nullptr) { Any result = run(); // 这里发生多态调用 m_result->setVal(std::move(result)); } } void Task::setResult(Result* res) { m_result = res; } main.cpp #include "threadpool.h" #include <chrono> #include <iostream> using std::cout; using std::endl; int main(int argc, char* argv[]) { { ThreadPool pool; pool.Start(4); Result res1 = pool.SubmitTask(std::make_shared<MyTask>(1, 100000000)); Result res2 = pool.SubmitTask(std::make_shared<MyTask>(100000001, 200000000)); Result res3 = pool.SubmitTask(std::make_shared<MyTask>(200000001, 300000000)); //uint64_t sum1 = res1.get().cast_<uint64_t>(); //uint64_t sum2 = res2.get().cast_<uint64_t>(); //uint64_t sum3 = res3.get().cast_<uint64_t>(); //cout << (sum1 + sum2 + sum3) << endl; } cout << "main over" << endl; getchar(); return 0; }
  17. 我创建了一个协作空间,所有者是我自己,我希望将所有权完全转移给另外一个人,然后我退出,应该怎么操作 我研究了下应该无法转移 [协作空间] 的所有权,也无法转移文件夹的所有权,难不成只能转移文档?很不合理啊,而且即便转移文档好像也无法把空间给他,他在这个空间里依然没有权限 或者批量导出,然后再导入新的文件夹下,创建新的 [协作空间] ,这样应该能解决问题,有没有更简单的方式
  18. 看静安 Apple 重新开业新闻有个退休老太太店员 突发奇想似乎这也是个出路 有 Apple Store 员工来现身说法一下么
  19. 先来说说我的需求: 数据可导出冷备份/可自建隐私化(最大的需求,自己的内容怎么也不想让任何第三方窥探) 强大的编辑器(文字格式样式傻瓜式调整、像语雀会员一样可以插入图片视频附件) 我不是很习惯用 markdown 编辑,换来换去,换成了编辑器最强大的群晖 note ! 之前用过 Joplin ,使用的 onedrive 同步,同步挺 6 的,然后电脑版和手机版 APP 都有 有道云笔记主力使用了十年+,后来泄露过一次隐私(有道云笔记的员工可以轻松看到你里面的内容,这个有时间细讲,简单说就是有一次我的同步出问题,找客服过程中,客服不小心说漏嘴了)还有有道云笔记目前免费版限制设备,这个就很逆天! 黑曜石也用过,虽然可以使用插件 webdav 同步,但没有时间和精力逐渐去习惯 印象笔记用过,现在妥妥的广告象!吃相很难看!而且免费版限制多! 语雀的编辑器倒是很合我胃口,但它的设计又不是单纯的笔记,数据还是全权给阿里托管... 思源啦什么的都用过,不尽人意... 最后说说目前群晖 Note 的一个不足吧: 不能创建导图,只能把导图导图贴图
  20. 几个月前联通运维时候上门拍照过,不玩 pcdn ,最近也控制了 nas pt 的上传速率,最近一两月上传了 1t-1.5t 上传。最近发现上传又被限速了,让联通师傅去查,又被怀疑是 pcdn 。反馈无果,联通让我自己把上传加速包取消,不给我恢复速率。求解
×
×
  • 创建新的...