diff --git a/README.md b/README.md index 2fc1f5cfdd11d788d47b26e5c2e2708aebcd0c1c..8b19d1a934be971df966ce88cdef0d919ee3146c 100644 --- a/README.md +++ b/README.md @@ -237,8 +237,8 @@ ## Java并发编程 -- [室友打了一把王者就学会了创建Java线程的3种方式](docs/thread/wangzhe-thread.md) -- [聊聊可以返回结果的创建线程的三个关键类:Callable、Future和FutureTask](docs/thread/callable-future-futuretask.md) +- [室友打了一把王者就学会了 Java 多线程](docs/thread/wangzhe-thread.md) +- [获取 Java 线程执行结果:Callable、Future和FutureTask](docs/thread/callable-future-futuretask.md) - [Java线程的6种状态及切换(透彻讲解)](docs/thread/thread-state-and-method.md) - [线程组是什么?线程优先级如何设置?](docs/thread/thread-group-and-thread-priority.md) - [进程与线程的区别是什么?](docs/thread/why-need-thread.md) diff --git a/docs/nice-article/juejin/zqjszjdxmjyzyfwmsfcl.md b/docs/nice-article/juejin/zqjszjdxmjyzyfwmsfcl.md new file mode 100644 index 0000000000000000000000000000000000000000..c301459aede66e7f2bc29b21463cadd124225cd5 --- /dev/null +++ b/docs/nice-article/juejin/zqjszjdxmjyzyfwmsfcl.md @@ -0,0 +1,224 @@ +--- +title: 🔥正确介绍自己的项目经验 再也不为面试发愁了 +shortTitle: 🔥正确介绍自己的项目经验 再也不为面试发愁了 +description: 在面试时,面试官一般都会问候选人简历中所列的项目,让介绍下项目经验。常见的问法是,说下你最近的一个项目。面试中很多人忽视对这一个环节的准备,甚至不知该如何去准备,本文就面试中项目经验的准备做了总结。 +tags: + - 优质文章 +author: Gaby +category: + - 掘金社区 +head: + - - meta + - name: keywords + content: 面试,前端 +--- + +--- +theme: cyanosis +highlight: zenburn +--- + +小知识,大挑战!本文正在参与“[程序员必备小知识](https://juejin.cn/post/7008476801634680869 \"https://juejin.cn/post/7008476801634680869\")”创作活动。 + +本文已参与「[掘力星计划](https://juejin.cn/post/7012210233804079141/ \"https://juejin.cn/post/7012210233804079141/\")」,赢取创作大礼包,挑战创作激励金。 + +废话只说一句:码字不易求个👍,收藏 === 学会,快行动起来吧!评论区走起🙇‍🙇‍🙇‍。 + + +在面试时,经过简单寒暄后,面试官一般先从让候选人自我介绍开始,紧接着就是问候选人简历中所列的项目,让介绍下项目经验。常见的问法是,说下你最近的(或感觉不错的)一个项目。面试中很多人忽视对这一个环节的准备,不仅回答不了面试官的追问,甚至连自己的项目都讲不清楚,说起来磕磕巴巴,甚至有的人说出的项目经验从时间段或技术等方面和简历上的不匹配,这样无疑会让面试官对面试者的能力产生怀疑。 + +面试时7份靠能力,3份靠技能,本文将从“前期准备”和“面试技巧”两大层面告诉大家如何准备面试时的项目介绍,当然,这只是一家之言,没有最好的方式,只有更适合的方法,仁者见仁智者见智。 + + +### 前期分析 + +1. **知己知彼百战不殆**。如果想打动面试官,那么你就必须得了解他到底想要从你口中了解到什么,哪些信息是他所想要的。 + + 在面试前准备项目描述时,别害怕,因为面试官什么都不知道,最了解你项目的还是你自己。 + + 面试官是人,不是神,拿到你的简历的时候,只能根据你所描述的项目去推测你的工作经历,是没法核实你的项目细节的(一般公司会到录用后,通过背景调查的方式来核实)。 + + 更何况,你做的项目是以月或以年为单位算的,而面试官最多用30分钟来从你的简历上了解你的项目经验,所以你对项目的熟悉程度要远远超过面试官,所以你一点也不用紧张。而面试官想了解更多他想知道的你的工作方式及项目中所负责的内容、所用到的技术栈,就不得不从你的介绍中去深挖技术点,以期了解你对项目及技术的了解的深度。 + + 首先从气势上就要告诉面试官,这项目就是你参与的,有你所负责的功能模块,让面试官不容置疑。 + + 心态上准备好了,那么就要分析面试官想要考察什么呢? + + - **表达能力**。考察表达及逻辑思维能力,看面试者能不能在几分钟就跟一个完全没有参与过项目的人讲清楚这个项目。 + - **实际工作经验**。你在项目中中承担了什么角色,做了什么工作。这些工作中的技术含量及跟同事合作情况如何。另外可能会针对某个项目,不断深入问一些技术上的问题,或者是从侧面问技术类实现,这是为了深入核实你做项目的细节及对技术的理解运用。 + - **解决问题能力**。一般都会问项目难点,其实就是想知道当你遇到技术或业务难点,是如何思考并解决问题的。 + - **项目复盘及经验总结能力**。哪里是自己觉得做的成功的,哪里觉得没做好的,是否还有继续优化的空间。自己所做的项目对个人能力有哪些提升。 + +2. **熟能生巧,对答自如**。 + + 首先是需要有个充足的准备,写项目经验一定要写自己熟悉的,因为面试官就会根据你写的项目经验提问。在面试前,就要在脑子里过一遍这个项目,准备好说辞,面试的时候自信点。讲清楚这个项目是满足什么需求的,开发过程中遇到哪些困难,自己怎么解决这些困难的。如果你经过充分准备,面试中也能答的很好,那面试官好感度就会增加,相反,如果面试中说的磕磕绊绊,那么可信度就会低了。 + +3. **明确目标,控盘引导**。 + + 在面试前,你需要明确自己的面试目的,就是通过面试,争取拿到 Offer 。 + + 最保守的方式就是在自己介绍项目的时候要么就是以面试官为主导,回答很简单,就是面试官问你一句你答一句。这会让面试官失去想了解你的信心,其次也会让自己错失表现自己,凸显重点思想的机会。做好防守虽然也是一种取胜的方式,但并非上策,很容易丢分。 + + 讲自己简历中所列的项目一定要很清晰明了有逻辑,埋下后续可能会提问到的技术点,也给面试官留下一个好印象。如果项目经验介绍的好,有逻辑和引导力,那么就会给自己带来以下两点明显的好处: + + 1. 给面试官带来的第一印象好,会让面试官感觉该候选人表述能力较强。 + 2. 一般来说,面试官会根据候选人介绍的项目背景来提问题,假设面试时会问10个问题,那么至少有5个问题会根据候选人所介绍的项目背景来问,候选人如果说的好,那么就可以很好地引导面试官去问后继问题,这就相当于把提问权完全交由自己控制了。 + + 如果你的工作经验比面试官还丰富的话,甚至还可以控制整个面试流程,甚至遇到 Nice 的面试官的话会以讨论的方式进行沟通。 + + | | 应聘者 | 面试官 | + | --------------- | ----- | --- | + | 对项目及技能了解程度 | 很了解 | 只能听你说,只能根据你说的内容做出判断 | + | 面试过程中的职责 | 在很短的时间内防守成功即可 | 如果不能全面了解,找不到你薄弱的地方就代表你做过 | + | 准备时间 | 面试前你有充足的时间准备 | 一般在面试前用30分钟阅读你的简历 | + | 沟通过程 | 你可以出错,但别出关键性的错误 | 不会太为难你,除非你太差 | + | 技巧 | 表达要有逻辑性,引导面试官提问,也可以从网上找其实就问些通用的有规律的问 | 足够多的面试题 | + + 既然面试官无法了解你的底细,那么他们怎么来验证你的项目经验和技术?下面总结了一些常用的提问方式。 + + + | 提问方式 | 目的 | + | --- | --- | + | 让你描述工作经验和项目(极有可能是最近的),说的是否和简历上一致 | 看看你看你是否真的做过这些项目 | + | 看你简历上项目里用到的技术,比如框架、数据库,然后针对这些技术提些基本问题 | 还是验证你是否做过项目,同时看你是否了解这些技术,为进一步提问做准备 | + | 针对某个项目,不断深入地问一些技术上的问题,或者从不同侧面问一些技术实现,看你前后回答里面是否有矛盾 | 深入核实你的项目细节 | + | 针对某技术,问些项目里一定会遇到的问题,比如候选人说做过数据库,那么就会问索引方面的问题 | 通过这类问题,核实候选人是否真的有过项目经验(或者还仅仅是学习经验) | + + + +### 面试技巧 + +内容上要对项目进行以下拆分,思考并进行总结,并试着口语化讲出来。 +1. **项目描述**。用通俗易懂且简洁的方式简述项目,阐述整个项目及其背景、规模,不要有太多的技术词汇。 +2. **项目模块**。2-3分钟的流程介绍,详细的列出项目实现的功能,各个模块,整个过程,大概思路。 +3. **项目技术栈**。说出项目实现的技术栈和架构,能说出项目的不寻常之处,比如采用了某项新技术,采用了某个架框等,简要说明技术选型。 +4. **候选人的角色及责任**。说出你在项目中的责任,所涉及的功能模块,运用的技术,碰到的难题、代码细节,技术点、应对措施。 +5. **项目总结,待优化点**。 + +方法上可以使用万能的STAR原则 + +Situation(背景):做这个项目的背景是什么,比如这是个人项目还是团队项目,为什么需要做这个 +项目,你的角色是什么,等等。\\ +Target(目标):该项目要达成的目标是什么?为了完成这个目标有哪些困难?\\ +Action(行动):针对所要完成目标,你做了哪些工作?如何克服了其中一些困难?\\ +Result(结果):项目最终结果如何?有哪些成就?有哪些不足之处可以改进? + +除了项目所取得的成绩之外,候选人还可以说明自己做完项目的感受,包括项目中哪些环节做的不错,哪些环节有提高的空间,自己在做这个项目中有何收获等。 + +无论是介绍自己的IT产品开发经历,还是在其他公司的实习项目经历,候选人都可以运用STAR法则来具体说明,轻松表现出自己分析阐述问题的清晰性、条理性和逻辑性。 + +但面试前如下的一些情况还是需要多加注意的。 + +1. **回答很简单**。问什么答什么,往往就一句话回答。如果你日常回答别人的问题或者之前面试中出现过类似情况就要有所改善了。这里应该将你知道的说出来,重点突出跟问题相关的思想、框架或技术点等。 + +2. **扯闲篇,大忌**。说少了太过于简短没有互动不好,自来熟,回答问题没有重点,没有逻辑,乱说一通也是大忌。会让面试官感觉你思路混乱,抓不到重点,只是拿其他方面的东西东拼西凑。 + +3. **说的太过流利**,也未必就是好事。虽然面试有所准备在面试官看来是好事,但是机械的准备好答案去背诵,主观上给人一种你并没有理解这个问题,只是靠记忆知道答案,后续面试官的问题也会相应的加大难度。这方面改善建议是适当停顿,做思考状,边思考边说,过程中同面试官有个眼神上的互动。 + +4. **有的放矢的介绍技术细节**。不要一次性过多的介绍技术细节,技术面点到为止,等面试官来问。因为面试官通常都有自己的面试节奏。所以技术点等着问的时候再多聊,可以先事先埋下技术点引导着面试官继续追问。 + +5. **主动介绍项目亮点**。因为面试官没有义务挖掘你的亮点,所以这就需要自己主动提。遇到不会的问题,就如实说这个技术点不会。或者半懂也可以直接说。甚至可以谈谈自己的见解。把自己了解的说说。 + +### 项目准备 + +一般来说,在面试前,大家应当准备项目描述的说辞,自信些,因为这部分你说了算,流利些,因为你经过充分准备后,可以知道你要说些什么。而且这些是你实际的项目经验(不是学习经验,也不是培训经验),那么一旦让面试官感觉你都说不上来,那么可信度就很低了。 + +不少人是拘泥于“项目里做了什么业务,以及代码实现的细节”,这就相当于把后继提问权直接交给面试官。下表列出了一些不好的回答方式。 + + +| 回答方式 | 后果 | +| --- | --- | +| 我在XX软件公司做了XX门户网站项目,这个项目做到了XX功能,具体是XX和XX模块,各模块做了XX功能,客户是XX,最后这个项目挣了XX钱 | 直接打断,因为业务需求我不需要了解,我会直接问他项目里的技术 | +| (需要招聘一个前端开发,会 React)最近一个项目我是用JQuery实现的,实现了....或者我最近做的不是开发,而是测试....或者我最近的项目没有用到 React | 提问,你最近用到React技术的项目是什么时候,然后在评语上写:最近XX时间没接触过 React | +| 在毕业设计的时候(或者在读书的时候,在学习的时候,在XX培训学校,在XX实训课程中) | 直接打断,提问你这个是否是商业项目,如果不是,你有没有其他的商业经验。如果没商业项目经验,除非是校招,否则就直接结束面试 | +| 描述项目时,一些关键要素(比如公司、时间、所用技术等)和简历上的不匹配 | 我们会深究这个不一致的情况,如果是简历造假,那么可能直接中断面试,如果真的是笔误,那么就需要提供合理的解释 | + + +在避免上述不好的回答的同时,大家可以按下表所给出的要素准备项目介绍。如果可以,也请大家准备一下用英语描述。 + +| 要素 | 样式 | +| --- | --- | +| 控制在1分钟里面,讲出项目基本情况,比如项目名称,背景,给哪个客户做,完成了基本的事情,做了多久,项目规模多大,用到哪些技术,数据库用什么,然后酌情简单说一下模块。重点突出背景,技术,数据库和其他和技术有关的信息。 | 我在XX公司做了XX外汇保证金交易平台,客户是XX银行,主要完成了挂盘,实盘成交,保证金杠杆成交等功能,数据库是Oracle,前台用到JS等技术,后台用到Java的SSH,几个人做了X个月。不需要详细描述各功能模块,不需要说太多和业务有关但和技术无关的。如果面试官感兴趣,等他问。 | +|要主动说出你做了哪些事情,这部分的描述一定需要和你的技术背景一致。| 我做了外汇实盘交易系统,挂单成交系统,XXX模块,做了X个月 | +| 描述你在项目里的角色 | 我主要是做了开发,但在开发前,我在项目经理的带领下参与了业务调研,数据库设计等工作,后期我参与了测试和部署工作。 | +| 可以描述用到的技术细节,特别是你用到的技术细节,这部分尤其要注意,你说出口的,一定要知道,因为面试官后面就根据这个问的。你如果做了5个模块,宁可只说你能熟练说上口的2个。| 用到了Java里面的集合,JDBC...等技术,用到了Spring MVC等框架,用技术连接数据库。 | +| 这部分你风险自己承担,如果可以,不露声色说出一些热门的要素,比如Linux,大数据,大访问压力等。但一旦你说了,面试官就会直接问细节。 | 这个系统里,部署在Linux上,每天要处理的数据量是XX,要求是在4小时,1G内存是的情况下处理完5千万条数据。平均访客是每分钟XXX。 | + +**不露痕迹地说出面试官爱听的话** + +在项目介绍的时候(当然包括后继的面试),面试官其实很想要听一些关键点,只要你说出来,而且回答相关问题比较好,这绝对是加分项。我在面试别人的时候,一旦这些关键点得到确认,我是绝对会在评语上加上一笔的。 + +下面列些面试官爱听的关键点和对应的说辞。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1bbb545ded24c80ab1ff6638e7cd6cd~tplv-k3u1fbpfcp-zoom-1.image) + +**一旦有低级错误,可能会直接出局** + +面试过程中有些方面你是绝对不能出错,所以你在准备过程中需要尤其注意如下的因素。下面列了些会导致你直接出局的错误回答。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/03381a51824b4f1e83486af0518d187a~tplv-k3u1fbpfcp-zoom-1.image) + +### 面试场景题 + +举一个例子,比如考察候选人是否聪明,star 法则会这样询问: + +1.在刚才的项目中,你提到了公司业务发展很快,人手不够,你是如何应对的呢? +2.在你的项目里面解决了什么样的难题 +3.在你的项目里面如何做的登录 +4.前端的项目如何进行优化,移动端呢? +5.图片加载失败要做啥 +6.让你带领一个小团队完成一个项目,你会怎么做? +7.项目的同源处理,跨域相关 +8.如果再做这个项目,你会在哪些方面进行改善? +面试中,如果面试官让你描述一个自己比较得意的项目的时候,一定记得要遵循 STAR 法则进行回答。比如 + +为了整合 xxx 业务(S),我承担 xxx 角色,具体负责 xxx (T)。做了 xxx 事情(A),最后产生了 xxx 结果 + +然后在描述项目亮点的时候也一样,比如 + +由于项目 xxx 原因(S),我需要进行 xxx 改进(T),然后进行了 xxx 处理(A),最后产出了 xxx 结果,数据对比为 xxx + +整体这样下来,会显得你很有思考力,且具有行动力,可以给企业创造出价值,这也是面试官评定候选人最关键的指标之一。 + + +**面试官的套路**\\ +面试时所问的问题基本分为两种:具象的问题和开放性的问题。 + +具象的问题基本都会参考工作经验按照 STAR 法则来进行,主要是了解基本的素养,技术深度和潜力。 + +开放性的问题基本是考察思维发散能力,考察在某个领域的深度和广度,基本上会结合技术问题来问,或者是结合工作内容来问。 + +比如:实现某种技术的 n 种方法?某种技术的实现原理?和什么什么相比有哪些优缺点?你对这项技术的思考是什么? + +**面试者的应对**\\ +1.就实际情况做回答,提前准备的时候多发散,多思考,多总结。这一块是可以自己准备的加分项。 + +2.发散性问题主要是看自己平时积累。首先基础知识要牢固,同时也要了解最新技术动态。面对这类问题切记也不能答非所问而跑题了。 + +## 注意: + +1.避免拿别人的项目直接用 + +很多初级阶段的同学们,可能并没有实际的商业项目,或者所做过的项目类型有限,就直接从网上找项目当做自己的项目,直接使用是断不可取的,但是如果你仿造别人的项目自己去尝试着将功能实现,有自己的新得体验,这样在做的过程中也可以对项目中的功能点和技术栈有进一步的了解,不至于在面试的时候,磕磕巴巴,甚至将项目时间都搞错。 + +2.避免低级错误 + +很多基础相关的低级错误一定要杜绝,如果被问到熟悉知识点就多答,不熟悉就直接说不熟悉。每个人都有自己擅长的点也有不擅长的。 + + +另外就是可以引导一些话题,不要自说自话。很多人会一直很激进的表达自己,反而显得强势。有的面试者被问到数据库相关内容,他不仅回答数据库,还会把大数据处理技术全部都说出来。其实点到为止最好,面试官感兴趣会继续问,但是你一直主导话题,会减分。 + +这里要说的是,不要把不是自己做的项目说成是自己做的,自己不是核心负责人说成是负责人,即使你对项目很熟悉了解,像我们一线起来的面试官,问几个问题就很清楚你实际参与了多少了,只是大部分不会明说而已,反而起到反效果。 + +## 总结 + +首先我要劝大家,认真对待每一次面试。既然知道自己要参加面试,就在家自己模拟一下面试。自己提前准备一下自己的项目描述,不要到了面试的时候去打磕巴。但是如果你参加面试的时候实在紧张了,磕巴了不要慌。深呼吸尝试让自己放松,一般面试官也会给些提示帮助你回答的。 + +两句话,第一,面试前一定要准备,第二,本文给出是的方法,不是教条,大家可以按本文给出的方向结合自己的项目背景做准备,而不是死记硬背本文给出的一些说辞。 + +*** +部分内容整理自网络 + + + +>参考链接:[https://juejin.cn/post/7017732278509453348](https://juejin.cn/post/7017732278509453348),整理:沉默王二 diff --git a/docs/nice-article/weixin/conghwtcdyhkjghn.md b/docs/nice-article/weixin/conghwtcdyhkjghn.md new file mode 100644 index 0000000000000000000000000000000000000000..b582d81a9fa280494fa467e4a53505e723011a9e --- /dev/null +++ b/docs/nice-article/weixin/conghwtcdyhkjghn.md @@ -0,0 +1,167 @@ +--- +title: 从华为跳槽到银行科技岗,好难! +shortTitle: 从华为跳槽到银行科技岗,好难! +author: 朱晋君 +category: + - 微信公众号 +--- + +![](https://mmbiz.qpic.cn/mmbiz_png/J0g14CUwaZclQSAM41A1ZnFukibKNKGiapfQQZJOKziaehj1pZzNHTicFkDKBMhTBzjZjys2GHM2nWd3LWt5SA7y0A/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1) + +图解学习网站:xiaolincoding.com + + + +大家好,我是小林。 + + + +今天分享一位面试官朋友在面试候选人时候的感触,可以从面试官的角度学一下,面试官问问题的时候, 实际上是想考察哪些能力。 + + + +下面是这位面试官朋友的分享。 + + + +* * * + +最近面试了很多候选人,感触很多,给大家分享一下。 + +今年我们团队在西安的招聘名额比较多,我作为团队的招聘组长,筛选了一波又一波的候选人。 + +西安是一个有实力的城市,名校云集,985/211 院校很多,包括西安交大、长安大学、西北工业大学、西安电子科技大学、西北大学、西北农林科技大学。多数候选人也是出自这些名校。 + +但是跟北京、上海、杭州这些互联网氛围浓厚的城市相比,西安的互联网氛围还是逊色一些。从我收到的简历看,候选人目前的岗位主要有下面四类: + +1. 银行科技公司的员工或者外包; +2. 华为西安研究所、腾讯云等大厂,岗位集中在云计算、大数据、devops 等,很多人有管理经验; +3. 互联网公司的外包岗位; +4. 其他不太知名的公司。 + +最近华为某个部门要撤离西安,整个团队面临迁移到别的城市的处境,这对于已经成家的员工来说,几乎不太可能。他们只能选择离职,我收到了不少相关候选人的简历。 + +下面的我摘出的一部分简历内容: + +> 使用技术:Spark、Hadoop、Clickhose、K8s 等。工作职责: +> +> 1. 主导大数据架构设计和技术选型; +> 2. 为数据流处理提供优化方案; +> 3. 新方案设计的推动落地实施; +> 4. 团队管理。 +> +> 擅长技能: +> +> 1. 熟悉 C++、Java、Linux 相关技术栈; +> 2. 熟悉 Spring、SpringBoot、SpringCloud 等框架; +> 3. 熟悉大数据相关技术,如 Kafka、flink、Spark 等; +> 4. 熟悉代码管理工具,如 maven、git 等; +> 5. 具体团队管理能力和经验。 +> +> 自我评价:编程能力强,热爱钻研技术,待人真诚,具有很强的抗压能力,良好的团队管理能力。 + +就从简历来看,候选人是很优秀的,学历背景优秀、大厂工作经历、带过团队、项目经验丰富。 + +我满怀期望跟候选人进行了沟通,但整个过程并不顺畅。 + +**我**:先简单介绍一下自己的情况。 + +**候选人**:我是在 xx 年毕业,毕业后经历了几家公司,...,从 xx 年开始我在 xx 研究所做云计算和大数据相关的工作。主要参与过 xx 项目。 + +**我**:详细介绍一个自己主导或者参与比较多的项目,包括项目中有哪些服务,用到了哪些技术栈,这些服务在业务流程中的作用,服务间怎么调用的。 + +**候选人**:xx 服务主要包括了 4 个服务,服务间通过 HttpClient 来进行通信 ... + +**先是自我介绍,然后深入介绍一个项目,这一般是我面试的开场套路。因为没有接触过候选人介绍的类似项目,我听得马马虎虎,假装听懂了。** + +**我**:你们微服务是怎么划分的,都有哪些服务?服务之间是怎么通信的? + +**候选人**:我们服务是部署在云上,... + +**我又是似懂非懂的,当面试官好难。要不纯问一些技术吧。** + +**我**:问你几个技术问题吧。给定一个长度为 n 包含 \[0, n\] 中 n 个数的数组 nums,**数组是有序的无重复的**,找出 \[0, n\] 这个范围内没有出现在数组中的那个数。(leetcode268 改编,改得更简单了)。 + +![](https://mmbiz.qpic.cn/mmbiz_png/a1gicTYmvicdicjMcRQtNeqVDJZfuOOnKHBUaPhvyAarZTWZFZrc12ox5m6YcJibke2xr76vTjtFLYMU3nBk6hqibAw/640?wx_fmt=png) + +**候选人**:新建一个长度为 n+1 的数组保存 \[0, n+1\] ,对原来的数组做循环依次查找每个元素是否在新建的数组中。 + +**我追问**:这个时间复杂度太高了,o(n^2),而且还需要额外空间,有更好的方法吗? + +**候选人**:我想想,(大概过了一分钟),不依赖外部数组,对原数组进行遍历,用数组下标加 1 和数组在当前下标的元素值进行比较,不相等就结束循环,最坏时间复杂度是o(n)。 + +**我追问**:还有更好的方法吗? + +**候选人**:我再想想,(大概过了 30 秒)想不出了。 + +**我又失望了一次,其实我想听到的答案是二分查找,用递归实现。** + +**我**:Java 中的 TreeMap 和 LinkedHashMap 有什么区别? + +**候选人**:TreeMap 是有序的,LinkedHashMap 记不清了。 + +**这里我想考察候选人的写代码情况,长期不写代码的人很容易记不清。** + +**我**:Java 中有哪些锁,可以讲一下吗? + +**候选人**:我们常用的是 synchronized。 + +**我**:Java AQS 中的锁使用过吗?候选人:好像有一个 reentrant 什么,记不清了。 + +**到这里,我感觉候选人应该主要做管理,已经很少做开发了。** + +**我**:使用 Spring 做依赖注入的时候,@Resource 和 @Autowired 有什么区别?**候选人**:@Autowired 是用类型来注入,@Resource 是用名字来注入。 + +**我追问**:这两个一般用在什么场景呢? + +**候选人**:我们一般使用 @Autowired 比较多,@Resource 用的很少。 + +**我**:(考虑到候选人是云计算岗)K8s 中的 deployment 和 statefulset 有什么区别呢?(**这个问题其实是为了缓解尴尬**) + +**候选人**:statefulset 用在有状态的应用,... + +**我**:(最后了)请问你离职的原因是什么? + +**候选人**:跟银行相比,华为还是不太稳定。为了节约成本,我们部门要撤掉,整体迁移到 xx 和 yy 两个城市,我家在西安,不太想去。 + +这个候选人我没给通过,原因有几点: + +1. 我招聘的这个岗位对于资深的候选人,入职后肯定要带团队; +2. 带团队不是只做管理,而是技术经理,需要能冲在一线,需要有不错的技术能力,有行业背景那就更好了; +3. 团队对每个人都是有代码考核的,不允许不写代码的同事存在; +4. 我要招一个人跟我做同事,当然希望基础好一些,这样可以对团队有一个很好的指导。 + +最后,分享几点自己的见解: + +1. 可以丢掉技术,但得有几个前提: + +* 要保证现在的工作足够稳定,不会被淘汰; +* 即使被淘汰了,也不担心,因为有丰富的人脉资源,可以帮助自己很快找到下一家管理岗; +* 不用担心经济问题,因为自己已经实现财富自由或者可以选择创业。 + +2. 面试中如果只是泛泛而谈,那不如直接说我不会,或者记不清了; +3. 社会对大龄程序员要求很高,技术、业务,高 P 的职位多数也要求懂管理; +4. 如果不是迫不得已,不要轻易换赛道,除非是 AI,ChatGPT 等很火的赛道。换了赛道,意味着之前的积累基本都会丢掉; +5. 今年的情况机会很难得,准备好了再去面试,不打没有准备的仗。 + + + + + +**历史好文:** + +[这个月,太多惊喜了!!!](http://mp.weixin.qq.com/s?__biz=MzUxODAzNDg4NQ==&mid=2247526533&idx=1&sn=c9aebdfa04b84bbac4791b49cfaf713d&chksm=f98d2c2fcefaa53963857be8e03c83b0008669d30136f7ad6e17f3fd40ecabc5818ae3be0d34&scene=21#wechat_redirect) **[](http://mp.weixin.qq.com/s?__biz=MzUxODAzNDg4NQ==&mid=2247526533&idx=1&sn=c9aebdfa04b84bbac4791b49cfaf713d&chksm=f98d2c2fcefaa53963857be8e03c83b0008669d30136f7ad6e17f3fd40ecabc5818ae3be0d34&scene=21#wechat_redirect)** + +[外面在鞭炮,而我还在写代码](http://mp.weixin.qq.com/s?__biz=MzUxODAzNDg4NQ==&mid=2247526545&idx=1&sn=c8d4e0f2a4755f187b28439111bcc762&chksm=f98d2c3bcefaa52dbafb00932792d00874b38311b97d5a831685949631bc82be9af7cbc53ee4&scene=21#wechat_redirect) + +[百度不问我项目,全程基础拷打,真扎心!](http://mp.weixin.qq.com/s?__biz=MzUxODAzNDg4NQ==&mid=2247526579&idx=1&sn=e5d3c69f2c6d3ae4d77ce0b5676bc766&chksm=f98d2c19cefaa50fd8d719190baab62bf2ee25216425b4f9f6ee03b5ea058f4bc8a34930c668&scene=21#wechat_redirect) + + + +[感觉被榨干了,被美团拷打一小时!](http://mp.weixin.qq.com/s?__biz=MzUxODAzNDg4NQ==&mid=2247526588&idx=1&sn=39d2bca8f21538399bba5906d72af250&chksm=f98d2c16cefaa5006917397742c85875f646cc863f520bfa6511fe24bce2791ec1e1475e4932&scene=21#wechat_redirect) + + + +[腾讯二面顶住了!评价反馈不错](http://mp.weixin.qq.com/s?__biz=MzUxODAzNDg4NQ==&mid=2247526456&idx=1&sn=91c449f268e0b132d97f33032bf81409&chksm=f98d2c92cefaa58489621f901108b7cfba44f2f7059111e39d5922c7c3589ed06acfb4c08e17&scene=21#wechat_redirect) + +>参考链接:[https://mp.weixin.qq.com/s?__biz=MzUxODAzNDg4NQ==&mid=2247526594&idx=1&sn=ac0d0453b137bf7f8e92c0beacded108&chksm=f98d2c68cefaa57e092455cb7da7aee4902bb43efe0fc16bc125dea3a7b7d79cc03b81ba94a5#rd](https://mp.weixin.qq.com/s?__biz=MzUxODAzNDg4NQ==&mid=2247526594&idx=1&sn=ac0d0453b137bf7f8e92c0beacded108&chksm=f98d2c68cefaa57e092455cb7da7aee4902bb43efe0fc16bc125dea3a7b7d79cc03b81ba94a5#rd),出处:小林coding,整理:沉默王二 diff --git a/docs/springboot/aop-log.md b/docs/springboot/aop-log.md index 95156fc52e9e8c1018712a1ecb063e989f460769..7a2fb426a5c02a361a48f7a9916e621711259e73 100644 --- a/docs/springboot/aop-log.md +++ b/docs/springboot/aop-log.md @@ -66,9 +66,7 @@ execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? @Pointcut("execution(public * com.codingmore.controller.*.*(..))") ``` - 表示 `com.codingmore.controller` 包下的所有 public 方法都要应用切面的通知。 - - +表示 `com.codingmore.controller` 包下的所有 public 方法都要应用切面的通知。 ### 三、实操 AOP 记录接口访问日志 diff --git a/docs/thread/callable-future-futuretask.md b/docs/thread/callable-future-futuretask.md index cef136fbcc89ce92a52eac725349ac30e2da1e94..1f7ac0c234f6d90677c91409ddc7d604d33cd565 100644 --- a/docs/thread/callable-future-futuretask.md +++ b/docs/thread/callable-future-futuretask.md @@ -1,24 +1,30 @@ --- -title: 聊聊可以返回结果的创建线程的三个关键类:Callable、Future和FutureTask -shortTitle: Callable、Future和FutureTask -author: Matrix海子 +title: 获取 Java 线程执行结果:Callable、Future和FutureTask +shortTitle: 获取线程执行结果 +description: 本文深入解释了如何在Java中使用Callable、Future和FutureTask来获取多线程执行结果。无论你是Java新手还是经验丰富的开发者,你都能在这里找到有用的信息和技巧。点击了解更多。 category: - - 博客园 + - Java核心 +tag: + - Java并发编程 +head: + - - meta + - name: keywords + content: Java, 多线程, Callable, Future, FutureTask, 线程执行结果 --- -# 14.2 Callable、Future 和 FutureTask +# 14.2 获取线程执行结果 -[在前面的文章中](https://tobebetterjavaer.com/thread/wangzhe-thread.html)我们讲述了创建线程的 3 种方式,一种是直接继承 Thread,一种就是实现 Runnable 接口,另外一种是 实现Callable 接口。 +[在第一节:初步掌握 Java 多线程中](https://tobebetterjavaer.com/thread/wangzhe-thread.html),我们讲述了创建线程的 3 种方式,一种是直接继承 Thread,一种是实现 Runnable 接口,另外一种是实现 Callable 接口。 -前 2 种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。 +前 2 种方式都有一个缺陷:在执行完任务之后无法获取执行结果。 -如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。 +如果需要获取执行结果,就必须通过共享变量或者线程通信的方式来达到目的,这样使用起来就比较麻烦。 -而自从 Java 1.5 开始,就提供了 Callable 和 Future,通过它们可以在任务执行完毕之后得到任务执行结果,之前我们简单聊过 Callable。今天我们就再来详细地讨论一下 Callable、Future 和 FutureTask 三个类的使用方法。 +Java 1.5 提供了 Callable、Future、FutureTask,它们可以在任务执行完后得到执行结果,今天我们就来详细的了解一下。 -### 一.Callable 与 Runnable +### 01、Callable 与 Runnable -先说一下 `java.lang.Runnable` 吧,它是一个接口,在它里面只声明了一个 run()方法: +由于 `Runnable` 的 `run()` 方法的返回值为 void: ```java public interface Runnable { @@ -26,9 +32,9 @@ public interface Runnable { } ``` -由于 `run()`方法返回值为 void 类型,所以在执行完任务之后无法返回任何结果。 +所以在执行完任务之后无法返回任何结果。 -Callable 位于 `java.util.concurrent` 包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做 `call()`: +Callable 位于 `java.util.concurrent` 包下,也是一个接口,它定义了一个 `call()` 方法: ```java public interface Callable { @@ -36,27 +42,75 @@ public interface Callable { } ``` -可以看到,这是一个泛型接口,`call()`函数返回的类型就是传递进来的 V 类型。 +可以看到,`call()` 方法返回的类型是一个 V 类型的[泛型](https://tobebetterjavaer.com/basic-extra-meal/generic.html)。 -那么怎么使用 Callable 呢?一般情况下是配合 ExecutorService 来使用的,在 ExecutorService 接口中声明了若干个 submit 方法的重载版本: +那怎么使用 Callable 呢? + +一般会配合 ExecutorService 来使用。 + +ExecutorService 是一个接口,位于 `java.util.concurrent` 包下,它是 Java 线程池框架的核心接口,用来异步执行任务。它提供了一些关键方法用来进行线程管理。 + +![](https://cdn.tobebetterjavaer.com/stutymore/callable-future-futuretask-20230619105509.png) + +下面的例子就用到了 ExecutorService 的 submit 方法。 ```java - Future submit(Callable task); - Future submit(Runnable task, T result); -Future submit(Runnable task); +// 创建一个包含5个线程的线程池 +ExecutorService executorService = Executors.newFixedThreadPool(5); + +// 创建一个Callable任务 +Callable task = new Callable() { + public String call() { + return "Hello from " + Thread.currentThread().getName(); + } +}; + +// 提交任务到ExecutorService执行,并获取Future对象 +Future[] futures = new Future[10]; +for (int i = 0; i < 10; i++) { + futures[i] = executorService.submit(task); +} + +// 通过Future对象获取任务的结果 +for (int i = 0; i < 10; i++) { + System.out.println(futures[i].get()); +} + +// 关闭ExecutorService,不再接受新的任务,等待所有已提交的任务完成 +executorService.shutdown(); ``` -第一个 submit 方法里面的参数类型就是 Callable。 +我们通过 Executors 工具类来创建一个 ExecutorService,然后向里面提交 Callable 任务,然后通过 Future 来获取执行结果。 -暂时只需要知道 Callable 一般是和 ExecutorService 配合来使用的,具体的使用方法讲在后面讲述。 +为了做对比,我们再来看一下使用 Runnable 的方式: -一般情况下我们使用第一个 submit 方法和第三个 submit 方法,第二个 submit 方法很少使用。 +```java +// 创建一个包含5个线程的线程池 +ExecutorService executorService = Executors.newFixedThreadPool(5); + +// 创建一个Runnable任务 +Runnable task = new Runnable() { + public void run() { + System.out.println("Hello from " + Thread.currentThread().getName()); + } +}; + +// 提交任务到ExecutorService执行 +for (int i = 0; i < 10; i++) { + executorService.submit(task); +} -### 二.Future +// 关闭ExecutorService,不再接受新的任务,等待所有已提交的任务完成 +executorService.shutdown(); +``` + +可以看到,使用 Runnable 的方式要比 Callable 的方式简单一些,但是 Callable 的方式可以获取执行结果,这是 Runnable 做不到的。 + +### 02、Future -Future 就是对于具体的 Runnable 或者 Callable 任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过 get 方法获取执行结果,该方法会阻塞直到任务返回结果。 +在前面的例子中,我们通过 Future 来获取 Callable 任务的执行结果,那么 Future 是什么呢? -Future 类位于 `java.util.concurrent` 包下,它是一个接口: +Future 位于 `java.util.concurrent` 包下,它是一个接口: ```java public interface Future { @@ -69,27 +123,31 @@ public interface Future { } ``` -在 Future 接口中声明了 5 个方法,下面依次解释每个方法的作用: +一共声明了 5 个方法: -- cancel 方法用来取消任务,如果取消任务成功则返回 true,如果取消任务失败则返回 false。参数 mayInterruptIfRunning 表示是否允许取消正在执行却没有执行完毕的任务,如果设置 true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论 mayInterruptIfRunning 为 true 还是 false,此方法肯定返回 false,即如果取消已经完成的任务会返回 false;如果任务正在执行,若 mayInterruptIfRunning 设置为 true,则返回 true,若 mayInterruptIfRunning 设置为 false,则返回 false;如果任务还没有执行,则无论 mayInterruptIfRunning 为 true 还是 false,肯定返回 true。 -- isCancelled 方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。 -- isDone 方法表示任务是否已经完成,若任务完成,则返回 true; +- `cancel()` 方法用来取消任务,如果取消任务成功则返回 true,如果取消任务失败则返回 false。参数 mayInterruptIfRunning 表示是否允许取消正在执行却没有执行完毕的任务,如果设置 true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论 mayInterruptIfRunning 为 true 还是 false,此方法肯定返回 false,即如果取消已经完成的任务会返回 false;如果任务正在执行,若 mayInterruptIfRunning 设置为 true,则返回 true,若 mayInterruptIfRunning 设置为 false,则返回 false;如果任务还没有执行,则无论 mayInterruptIfRunning 为 true 还是 false,肯定返回 true。 +- `isCancelled()` 方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。 +- `isDone()` 方法表示任务是否已经完成,若任务完成,则返回 true; - `get()`方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回; - `get(long timeout, TimeUnit unit)`用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回 null。 也就是说 Future 提供了三种功能: -1)判断任务是否完成; +- 1)判断任务是否完成; +- 2)能够中断任务; +- 3)能够获取任务执行结果。 -2)能够中断任务; +由于 Future 只是一个接口,如果直接 new 的话,编译器是会有一个 ⚠️ 警告的,它会提醒我们最好使用 FutureTask。 -3)能够获取任务执行结果。 +![](https://cdn.tobebetterjavaer.com/stutymore/callable-future-futuretask-20230619111245.png) -因为 Future 只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的 FutureTask。 +实际上,FutureTask 是 Future 接口的一个唯一实现类,我们在前面的例子中 `executorService.submit()` 返回的就是 FutureTask,通过 debug 模式可以观察到。 -### 三.FutureTask +![](https://cdn.tobebetterjavaer.com/stutymore/callable-future-futuretask-20230619111830.png) -我们先来看一下 FutureTask 的实现: +### 03、FutureTask + +我们来看一下 FutureTask 的实现: ```java public class FutureTask implements RunnableFuture @@ -114,121 +172,55 @@ public FutureTask(Runnable runnable, V result) { } ``` -事实上,FutureTask 是 Future 接口的一个唯一实现类。 - -## 四.使用示例 - -1.使用 Callable+Future 获取执行结果 +来个例子 ```java -public class Test { - public static void main(String[] args) { - ExecutorService executor = Executors.newCachedThreadPool(); - Task task = new Task(); - Future result = executor.submit(task); - executor.shutdown(); - - try { - Thread.sleep(1000); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } - - System.out.println("主线程在执行任务"); - - try { - System.out.println("task运行结果"+result.get()); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); +// 创建一个固定大小的线程池 +ExecutorService executorService = Executors.newFixedThreadPool(3); + +// 创建一系列 Callable +Callable[] tasks = new Callable[5]; +for (int i = 0; i < tasks.length; i++) { + final int index = i; + tasks[i] = new Callable() { + @Override + public Integer call() throws Exception { + TimeUnit.SECONDS.sleep(index + 1); + return (index + 1) * 100; } - - System.out.println("所有任务执行完毕"); - } + }; } -class Task implements Callable{ - @Override - public Integer call() throws Exception { - System.out.println("子线程在进行计算"); - Thread.sleep(3000); - int sum = 0; - for(int i=0;i<100;i++) - sum += i; - return sum; - } + +// 将 Callable 包装为 FutureTask,并提交到线程池 +FutureTask[] futureTasks = new FutureTask[tasks.length]; +for (int i = 0; i < tasks.length; i++) { + futureTasks[i] = new FutureTask<>(tasks[i]); + executorService.submit(futureTasks[i]); } -``` -执行结果: +// 获取任务结果 +for (int i = 0; i < futureTasks.length; i++) { + System.out.println("Result of task" + (i + 1) + ": " + futureTasks[i].get()); +} -``` -子线程在进行计算 -主线程在执行任务 -task 运行结果 4950 -所有任务执行完毕 +// 关闭线程池 +executorService.shutdown(); ``` -2.使用 Callable+FutureTask 获取执行结果 +来看一下输出结果 -```java -public class Test { - public static void main(String[] args) { - //第一种方式 - ExecutorService executor = Executors.newCachedThreadPool(); - Task task = new Task(); - FutureTask futureTask = new FutureTask(task); - executor.submit(futureTask); - executor.shutdown(); - - //第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread - /*Task task = new Task(); - FutureTask futureTask = new FutureTask(task); - Thread thread = new Thread(futureTask); - thread.start();*/ - - try { - Thread.sleep(1000); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } - - System.out.println("主线程在执行任务"); - - try { - System.out.println("task运行结果"+futureTask.get()); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - - System.out.println("所有任务执行完毕"); - } -} -class Task implements Callable{ - @Override - public Integer call() throws Exception { - System.out.println("子线程在进行计算"); - Thread.sleep(3000); - int sum = 0; - for(int i=0;i<100;i++) - sum += i; - return sum; - } -} +``` +Result of task1: 100 +Result of task2: 200 +Result of task3: 300 +Result of task4: 400 +Result of task5: 500 ``` -如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 `Future` 形式类型、并返回 null 作为底层任务的结果。 - -> 参考链接:[http://www.cnblogs.com/dolphin0520/p/3949310.html](http://www.cnblogs.com/dolphin0520/p/3949310.html),整理:沉默王二 - - ----- - -GitHub 上标星 7600+ 的开源知识库《[二哥的 Java 进阶之路](https://github.com/itwanger/toBeBetterJavaer)》第一版 PDF 终于来了!包括Java基础语法、数组&字符串、OOP、集合框架、Java IO、异常处理、Java 新特性、网络编程、NIO、并发编程、JVM等等,共计 32 万余字,可以说是通俗易懂、风趣幽默……详情戳:[太赞了,GitHub 上标星 7600+ 的 Java 教程](https://tobebetterjavaer.com/overview/) +--- +GitHub 上标星 7600+ 的开源知识库《[二哥的 Java 进阶之路](https://github.com/itwanger/toBeBetterJavaer)》第一版 PDF 终于来了!包括 Java 基础语法、数组&字符串、OOP、集合框架、Java IO、异常处理、Java 新特性、网络编程、NIO、并发编程、JVM 等等,共计 32 万余字,可以说是通俗易懂、风趣幽默……详情戳:[太赞了,GitHub 上标星 7600+ 的 Java 教程](https://tobebetterjavaer.com/overview/) 微信搜 **沉默王二** 或扫描下方二维码关注二哥的原创公众号沉默王二,回复 **222** 即可免费领取。 -![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/gongzhonghao.png) \ No newline at end of file +![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/gongzhonghao.png) diff --git a/docs/thread/wangzhe-thread.md b/docs/thread/wangzhe-thread.md index e78a0a1393e24ee5908e4560522b630e10768f70..e25c5a7d937c4e9e4ad887cf71c64711a11a7807 100644 --- a/docs/thread/wangzhe-thread.md +++ b/docs/thread/wangzhe-thread.md @@ -1,54 +1,58 @@ --- -title: 室友打了一把王者就学会了创建Java线程的3种方式 -shortTitle: 创建Java线程的3种方式 +title: 室友打了一把王者就学会了 Java 多线程 +shortTitle: 初步掌握 Java 多线程 category: - Java核心 tag: - Java并发编程 -description: 室友打了一把王者就学会了创建Java线程的3种方式 +description: 在王者荣耀的战场上,室友不仅找到了娱乐,还找到了编程的灵感。通过玩游戏,他理解了Java多线程的运行原理。点击进入,了解他的故事和学习经验,也许你也能在游戏中找到学习编程的新方法。 head: - - meta - name: keywords content: Java,并发编程,多线程,Thread --- -# 14.1 创建多线程的 3 种方式 +# 14.1 初步掌握 Java 多线程 对于 Java 初学者来说,多线程的很多概念听起来就很难理解。比方说: - 进程,是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现了操作系统的并发。 -- 线程,是进程的子任务,是CPU调度和分派的基本单位,实现了进程内部的并发。 +- 线程,是进程的子任务,是 CPU 调度和分派的基本单位,实现了进程内部的并发。 -很抽象,对不对?打个比喻,你在打一把王者(其实我不会玩哈doge): +很抽象,对不对?打个比喻,你在打一把王者(其实我不会玩哈 doge): - 进程可以比作是你开的这一把游戏 - 线程可以比作是你所选的英雄或者是游戏中的水晶野怪等之类的。 带着这个比喻来理解进程和线程的一些关系,一个进程可以有多个线程就叫多线程。是不是感觉非常好理解了? +### 01、进程和线程 + **❤1、线程在进程下进行** -(单独的英雄角色、野怪、小兵肯定不能运行) +(单独的英雄角色、野怪、小兵肯定不能运行) **❤2、进程之间不会相互影响,主线程结束将会导致整个进程结束** -(两把游戏之间不会有联系和影响。你的水晶被推掉,你这把游戏就结束了) +(两把游戏之间不会有联系和影响。你的水晶被推掉,你这把游戏就结束了) **❤3、不同的进程数据很难共享** -(两把游戏之间很难有联系,有联系的情况比如上把的敌人这把又匹配到了) +(两把游戏之间很难有联系,有联系的情况比如上把的敌人这把又匹配到了) **❤4、同进程下的不同线程之间数据很容易共享** -(你开的那一把游戏,你可以看到每个玩家的状态——生死,也可以看到每个玩家的出装等等) +(你开的那一把游戏,你可以看到每个玩家的状态——生死,也可以看到每个玩家的出装等等) **❤5、进程使用内存地址可以限定使用量** -(开的房间模式,决定了你可以设置有多少人进,当房间满了后,其他人就进不去了,除非有人退出房间,其他人才能进) +(开的房间模式,决定了你可以设置有多少人进,当房间满了后,其他人就进不去了,除非有人退出房间,其他人才能进) + +### 02、创建线程的三种方式 -搞清楚上面这些概念之后,我们来看一下多线程创建的两种方式: +搞清楚上面这些概念之后,我们来看一下多线程创建的三种方式: -♠①:创建一个类继承Thread类,并重写run方法。 +♠①:创建一个类继承 Thread 类,并重写 run 方法。 ```java public class MyThread extends Thread { @@ -80,11 +84,9 @@ t3.start(); 来看一下执行后的结果: - ![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/thread/wangzhe-thread-01.png) - -♠②:创建一个类实现Runnable接口,并重写run方法。 +♠②:创建一个类实现 Runnable 接口,并重写 run 方法。 ```java public class MyRunnable implements Runnable { @@ -121,8 +123,7 @@ t3.start(); ![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/thread/wangzhe-thread-02.png) -♠③:实现Callable接口,重写call()方法,这种方式可以通过FutureTask获取任务执行的返回值。 - +♠③:实现 Callable 接口,重写 call 方法,这种方式可以通过 FutureTask 获取任务执行的返回值。 ```java public class CallerTask implements Callable { @@ -148,25 +149,39 @@ public class CallerTask implements Callable { } ``` - -**❤1、为什么要重写run方法?** +### 03、关于线程的一些疑问 + +**❤1、为什么要重写 run 方法?** + +这是因为默认的`run()`方法不会做任何事情。 + +为了让线程执行一些实际的任务,我们需要提供自己的`run()`方法实现,这就需要重写`run()`方法。 + +```java +public class MyThread extends Thread { + public void run() { + System.out.println("MyThread running"); + } +} +``` -因为run方法是用来封装被线程执行的代码。 +在这个例子中,我们重写了`run()`方法,使其打印出一条消息。当我们创建并启动这个线程的实例时,它就会打印出这条消息。 **❤2、`run()`方法和`start()`方法有什么区别?** - `run()`:封装线程执行的代码,直接调用相当于调用普通方法。 -- `start()`:启动线程,然后由JVM 调用此线程的 `run()` 方法。 +- `start()`:启动线程,然后由 JVM 调用此线程的 `run()` 方法。 **❤3、通过继承 Thread 的方法和实现 Runnable 接口的方式创建多线程,哪个好?** -实现Runable接口好,原因有两个: +实现 Runable 接口好,原因有两个: -- ♠①、避免了Java单继承的局限性 -- ♠②、适合多个相同的程序代码去处理同一资源的情况,把线程、代码和数据有效的分离,更符合面向对象的设计思想。 +- ♠①、避免了 Java 单继承的局限性,Java 不支持多重继承,因此如果我们的类已经继承了另一个类,就不能再继承 Thread 类了。 +- ♠②、适合多个相同的程序代码去处理同一资源的情况,把线程、代码和数据有效的分离,更符合面向对象的设计思想。Callable 接口与 Runnable 非常相似,但可以返回一个结果。 -针对线程控制,大家还会遇到 3 个常见的方法,我们来一一介绍下。 +### 04、控制线程的其他方法 +针对线程控制,大家还会遇到 3 个常见的方法,我们来一一介绍下。 1)`sleep()`:使当前正在执行的线程暂停指定的毫秒数,也就是进入休眠的状态。 @@ -180,7 +195,7 @@ try {//sleep会发生异常要显示处理 } ``` -2)`join()`:等待这个线程执行完才会轮到后续线程得到cpu的执行权,使用这个也要抛出异常。 +2)`join()`:等待这个线程执行完才会轮到后续线程得到 cpu 的执行权,使用这个也要捕获异常。 ```java //创建MyRunnable类 @@ -204,7 +219,6 @@ t3.start(); ![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/thread/wangzhe-thread-03.png) - 3)`setDaemon()`:将此线程标记为守护线程,准确来说,就是服务其他的线程,像 Java 中的垃圾回收线程,就是典型的守护线程。 ```java @@ -230,10 +244,9 @@ t3.start(); ![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/thread/wangzhe-thread-04.png) ----- - -GitHub 上标星 7600+ 的开源知识库《[二哥的 Java 进阶之路](https://github.com/itwanger/toBeBetterJavaer)》第一版 PDF 终于来了!包括Java基础语法、数组&字符串、OOP、集合框架、Java IO、异常处理、Java 新特性、网络编程、NIO、并发编程、JVM等等,共计 32 万余字,可以说是通俗易懂、风趣幽默……详情戳:[太赞了,GitHub 上标星 7600+ 的 Java 教程](https://tobebetterjavaer.com/overview/) +--- +GitHub 上标星 7600+ 的开源知识库《[二哥的 Java 进阶之路](https://github.com/itwanger/toBeBetterJavaer)》第一版 PDF 终于来了!包括 Java 基础语法、数组&字符串、OOP、集合框架、Java IO、异常处理、Java 新特性、网络编程、NIO、并发编程、JVM 等等,共计 32 万余字,可以说是通俗易懂、风趣幽默……详情戳:[太赞了,GitHub 上标星 7600+ 的 Java 教程](https://tobebetterjavaer.com/overview/) 微信搜 **沉默王二** 或扫描下方二维码关注二哥的原创公众号沉默王二,回复 **222** 即可免费领取。