java经验总结

2024-08-18

java经验总结(共8篇)

1.java经验总结 篇一

可视化快递追踪分析平台- VisualExpress

软件环境: j2ee

硬件环境: x86

开发工具: Java

项目描述: 该项目旨在开发一个可以向用户提供基于Google Map的可视化快递单件查询,提供RSS、手机短信、Email等多种单件状态信息订阅,能够利用既往数据进行单件到达时间预测,并对快递公司的整体运营情况进行简单分析的综合快递交互平台。 责任描述: 任务分配、项目模块划分、项目进度监督以及相关人员的协调(项目组共6人)。需求分析、模块功能的取舍裁定以及模块之间的接口定义。利用Struts和JSP编写系统表示层的相关代码。相关文档和项目报告的编写。

2.java经验总结 篇二

1 逆向绘制Java类图

逆向工程它是一个支持统一建模语言UML的面向对象的可视化分析、设计建模的工具, 其设计可以完成面向对象方法所需要的四层模型的设计与维护, 其中这四项模型是:用例模型、类和对象模型、组件模型和分布处理模型, 在具体的制图过程中, 通过逐层建模最后生成所需要开发环境的源代码, 并且可以根据应用程序进行系统的逆向建模。然而在绘制具体的Java类图中, 通过逆向建模在进行可视化的基础上, 将关系提取的准确性以及软件设计模式和程序代码进行演化, 最终产生对可视化的具体影响。

在绘制类图的过程中, 由于其中面临着多重性的问题, 因此在不同的应用领域需要对系统进行特定的设计模式和体系结构的调整, 需要建立精确的关系来将软件进行设计模式和程序结构的开发, 在Java程序进行的逆向可视化中, 需要将软件的演进过程, 在动画或者是不同颜色的区分中来划分具体的版本, 最终了解结构之间的差异, 以及观察具体的变化过程。因此在层次制图的过程中, 需要综合的考虑UML类图的规范、软件设计模式以及程序的演化过程, 重点研究Java可视化方法。

2 可视化技术

在研究Java可视化程序中, UML类图是由节点和边组成的复杂图, 并且在图元之间存在着关系, 具体的研究方法是:在研究一般图的基础上添加包含关系映射, 最终扩展为复合图。然后定义ULM类图语义映射将复合图确定为扩展类图。最终确定为扩展类图的节点图元有类、接口、包、注释, 关系图元有继承、聚集、实现、锚定以及有向关联。通常在可视化模型的建立中, UML类图的扩展图是将entiy为节点, 集合成V并且最终到UML类图的节点图元的映射中, 这两个映射之间是一对一的关系。

可视化程序的主要步骤可以归纳为:在研究可视化程序的基础上, 首先是要去除自环边、压缩注释、删除孤立节点和划分模式子图来具体的调整UML类图的模型设计, 但是在模型的研究中需要对具体的节点以及排列顺序进行具体的研究, 避免其影响布图的结果。在具体的模型建立中, 需要第模式子图进行详细的划分, 具体的要求根据软件设计模式来将类图中的包图元连同其子元素进行划分到不同的子图中, 在Java可视化程序中, 在通过计算不同的包与类库中界面。数据库以及包间的距离等, 将具体的设计划分为包图不同式的子图当中, 确定包图的具体是根据D=▕A+I-I▕/2, 式子中A作为包的抽象度, I是包不稳定度。

然后将UML类图进行调整, 将集合分为层次边和非层次边, 并且在深度优先遍历的方法中反转以及反馈边, 最终将未出现环的图进行划分, 在划分中需要根据节点的优先级以及边的权来将图中的环分配到节点中, 在划分的过程中, 需要考虑的是边拐点数目以及边长度的最小化, 确定好边的分层, 具体的操作步骤是:将节点优先级用其入度表示, 将入度大的节点优先放置在图的正中间, 而Length表示的是边的长度, Weight表示的是边的权重。其权性高的边分配的边长比较短, 因此需要根据权值来确定边长度。利用这样的表示方法来确定目标函数, 利用网络单纯形法来接函数, 完成对层次划分图的结构布置。在使用UML类图的基础上, 根据逐层最小化算法, 对节点以及边进行添加UML语义, 将映射来划分图转化为类图, 然后将类图中的符合节点进行展开, 按照坐标计算的原则来将图元的层次的纵坐确定, 而横坐边是按照同层的图元的相邻顺序排列分配。在横坐标和纵坐标的划分中需要考虑图元之间的空隙以及边拐点的控制, 利用边都是由水平和垂直的线段具体组成。最终完成UML类图的转化, 将Java可视化程序进行验证。

3 总结

通过分析层次布图法, 然后从逆向工程的角度进行具体研究, 在分析了支持类关系精度中提取, 将可视化软件模式以及软件在演化中进行了不断的扩展分析, 最终实现了支持Venus系统的可视化Java程序, 在该逆向软件工程设计中, 复合UML类图的语义, 将层次具体的划分, 并且支持图元嵌套的关系, 这种逆向绘制的Java类图能够更加准确的将软件的设计模式划分为子图, 并且具体的相互转化, 推动了软件的演化过程, 另外在添加图元中采用增量进行插入, 使同一种程序可以在不同版本之间以及颜色的区分中绘制更多的类图, 并且保持一致性。基于UML类图的Java可视化程序中, 能够将关联边比较多的图, 具体的确定关联距, 确定逐层最小化, 保证关联关系的最小化, 确定好横坐标以及纵坐标之间的距离, 为推动Java程序的进一步可视化软件更新提供了有利的准备, 加大了软件的扩展性, 以及转化性。

摘要:随着软件技术在不断的更新, 软件可视化在软件逆向工程中发挥着重要的作用, 该软件自身具有直观以及比较容易理解的优势。然而在软件的开发技术中, 面对对象软件在结构UML类图中能够为工程师们提供更加容易理解的Java程序。因此本文针对逆向工程对Java程序进行可视化分析, 根据其中面临的问题进行研究, 在UML类图中从支持类关系中进行精确的提取, 对软件进行模式以及版本演化, 并且进行了可视化的扩展分析, 最终实现了可视化系统中的Venus技术应用, 推动了软件技术的更新。

关键词:UML类图,Java程序可视化

参考文献

[1]李荣荣, 樊博.JAVA语言理解中算法可视化表示和实现的研究[J].信息工程, 2012 (15) .

[2]王小波, 刘建斌, 邓敏.可视化面向对象Java程序设计工具的研究[J].计算机科学, 2013 (14) .

3.经验总结的经验 篇三

任何组织都存在一个经验的自然传播过程,上下级之间的工作指导,师傅与徒弟的传帮带,年终或季度总结会上的回顾,同事之间平时的聊天,同一个项目组在工作配合时的互相学习等,都会把好的经验传播开。

但是,按照整体目标复制销售团队经验,必须对“经验发现和经验提炼”过程进行管理。这就包含两个过程:

发现和收集经验

实际上,在每一个团队中,每一个销售人员的实践中都隐藏着很多经验教训,但通常是分散的,不成系统。让他们在日常业务工作中整理、加工和传递自己的经验,是不太容易的。这个过程不会自然发生,需要有效的管理,要赋予每个团队和每个人员以承担这项责任的意愿和能力。

具体方法就是对日常的销售会议制度和日报制度进行改造。

改造日常销售会议制度的要点

通过销售会议弄清楚:

哪些经验对销售人员最有价值?业绩好的团队与差的团队,其行为和能力差异何在?销售人员当天处理的最大问题是什么?他们在业务工作中感觉最吃力的是什么?他们在工作中最欠缺的能力是什么?从自身和团队的角度,业绩提高的障碍是什么?

改造日报制度的要点

让销售人员接受这样一个基本理念:要使上司的决策有助于销售业务的展开和业绩提升,他必须向上司贡献自己掌握的信息、知识、经验、对策和信念。他必须时时问自己:应该报告一些什么,才能让上司做出正确的决策。

同时,依靠制度性规范约束销售人员,按照规定的要求做出报告:

事情的背景是什么?发生了什么?涉及哪些关键方面?事情的进展遇到哪些问题?针对问题采取了什么对策?取得了什么效果?有何改进?有何风险或机会?有何具体的对策?

如果需要寻找系统思考问题和综合解决问题的经验典范,就要找到最优秀的团队和最优秀的销售人员,追踪业绩最好的团队,追踪最成功的案例。

因此,日常销售会议制度的重点是:关注优秀的市场和优秀的团队,关注成功的典型案例。日报制度的重点是:关注所有团队、全部销售人员,关注他们每天的具体业务工作。

提炼和总结经验

销售团队的经验要能大规模、有组织地复制,必须经过系统化、知识化的总结提炼,一般分为两个方面:

一是提炼成完整的案例,展示一个团队对市场的系统思考以及综合解决问题的过程,比如进入一个空白市场的案例,主要表现为团队作业的整体经验;

二是提炼出解决“关键过程以及难点”的有效办法,主要表现为个人的独到经验。

完整案例提炼法

要提炼完整案例,就需要在每项重要任务或者关键活动之后,进行回顾总结——无论成功还是失败。而且,必须以故事的方式进行总结,使之富有感染力,易于接受。

这些经验案例中包含着创新的方法、有效的谈判技巧、团队的良好合作、对市场的独到理解、思路复杂而操作简单的方案等,都需要演绎成故事,不仅要经常被讨论、学习和思考,而且要被口头传播给新员工。

演绎成故事并不需要夸张,而是把经验发生的前因后果交代清楚。在陈述事实之外,多去关注当事人的想法和思维过程,强调达成目标的阶段、困难和方法。像传诵英雄事迹一样去重视这些最佳实践,这样经验才更容易传播。销售人员也因为感觉被关注、被依靠、被认同,而更有成就感和归属感。

总结案例时,容易产生的误区是:当面交流起来很好的经验一旦变成纸上的,大部分信息就被遗漏,活生生的事例变成死板的文字。我们需要的经验,变成文字后往往只是一些信息。那些让人豁然开朗、激动人心的东西再也找不出来,经验复制就会变成形式主义,毫无价值。

要避免这个问题,重点案例一定要讲清楚来龙去脉,与其给团队员工提供10个简单故事,不如把一两个案例阐述透彻。真正产生价值、达到复制团队效果的经验案例不是普遍性的原则,而是具体的做法,是事情发生的过程,是经验教训。

这就需要企业安排专门的人员,比如人力资源部的培训部门,跟踪重点案例的采集,而不是让销售人员自己总结——他们往往没有精力,也没有专长去用文字阐述一个完整的过程。

有效的做法是:让有营销工作经验的培训部专门人员,按照一个完整的逻辑结构,采访每一个重要的当事人,详细记录每一个重要的细节。案例总结过程就是一个研究的过程。

个人经验提炼法

总结日常业务工作的经验,是每个优秀业务员必须养成的良好习惯,这种制度在大多数企业都被使用过,但做得好的很少。大多数时候都会走样,变成应付上司的任务,或变成不认真填,或者确实不知道怎么填写报表反馈的信息没有人去关注,提出的困难没有人去帮助——本来还有一部分人在认真填写,因为管理者不关注,逐渐地也丧失了积极性。

如何避免这种形式主义,让销售人员养成反思和总结的习惯,不是靠几张表格可以实现的,必须通过会议和讨论等方式,围绕他们日常工作流程上的要点和难点来总结,帮助他们深入剖析业务过程,关注那些花费他们大量精力、让他们头疼、又能让他们一讨论就兴奋的事,让他们体会到通过反思和讨论找到成长的兴奋感。

关键过程和难点上的经验,可以从每周总结“三点经验”和“三点教训”做起。

1.总结。

三点经验和三点教训的总结过程,不可能一蹴而就、一步到位,要循序渐进,尤其需要基层团队经理的重视和组织。具体做法可以如下:

把每个人的经验教训拿出来讨论,每次指定2~3人,不仅把三点经验和三点教训说出来,更要回顾事情发生的过程,回到事情的目的、计划和实际的进展上。不管是经验还是教训,都要多问为什么。主管上级要指导帮助,提出具体改进建议,让当事人体会到反思和总结的价值,最终让其进入反思角色,养成反思习惯。

如果每周总结太频繁,也可以在完成一项工作后总结。尤其是团队协作的活动中,小而简单的事可以少花时间,比如一小时;大而复杂的活动结束后,就是花上半天或一天的时间来总结,也是值得的。

2.汇邑。

三点经验和三点教训汇总起来,就是关键过程的操作指南,是难点问题的改进办法,是销售人员能力提升的经验点。

汇总要从基层团队开始,从5~8个人独立的行动团队开始,比如一个项目组,或一个地市业务团队。汇总时不需要掺杂个人意见,录入电脑并按照要求归类即可。

然后以分公司或业务部门为单位,进行第二次汇总,这时候就需要总结提炼而不仅仅是汇总。按照专题和重要顺序整理好,从中发现可以进一步挖掘总结的经验亮点,总部可以围绕这些亮点进一步编写专题性的案例。

所有的经验和教训到公司总部再进行第三次汇总,根据实际运作的成效,一般在第二天就可以下发到各分公司供学习参考。

提示:团队经验总结提炼能否执行到位的关键

基层团队和营销人员的经验能否转变为原始信息,取决于团队经理能不能让他们把有效的信息表达出来。

为让基层重视,可以把经验总结作为基层团队经理和分公司经理的考核指标。基层团队经理由他的直接上级评价,分公司由总部的培训部门评价,评价的依据就是信息反馈的情况。

4.java经验总结 篇四

一些Java软件工程师求职者们,可能因为种种原因,对Java语言及其深层原理掌握不牢固,以至于在面试中犯各种错误。本期乔布简历小编将为大家带来的主题是java程序员面试经验,一起来了解一下java程序员面试宝典吧~

关键词:java程序员面试宝典,java程序员面试经验

以下是一些java程序员面试需要注意的地方:

1、对于此类岗位而言,具体的项目是用人单位招聘时最看重的参考因素。即便是没有工作经验的应届生,也要准备可作为自己能力参考的具体作品。如果从未参加过任何项目,可以准备自己在相关领域的课程设计,如有必要还可以将其修改为完整的项目。对于这份具体作品,求职者要有相当的了解。通过求职者对于该作品的讲解,招聘官会判断求职者的技术能力到底如何。

2、Java程序员要求掌握的技能会比较多,求职者在简历上可以分类依次列举出自己所掌握的专业技能,有证书的列出自己所持有的证书名称。在面试的时候,可以对自己所掌握的技能做出介绍,并辅以实例证明,这样会更具有说服力。

3、基础很重要,不要生疏了。不管应聘什么程序员岗位,基础永远都是最重要的。只有有了踏实的基础,再辅以较好的学习能力,这样才不会被互联网日新月异的变化甩开。很多程序员在面试时往往是因为答不出最基础的问题才会错失工作机会。面试前巩固一下基础知识,永远不要轻视了基础。

程序员要时刻关注技术前沿,将新技术与自己所从事的工作联系到一起,做一些深入思考,面试时谈谈这样的问题也是向面试官展现自己学习能力的好机会~

5.java经验总结 篇五

1.下面关于java.lang.Exception正确的说法是_____________。

A.继承自Throwable B.Serializable 序列化 C.集成自Error D.以上都不正确

2.______模式通过提供与对象相同的接口来控制对这个对象的访问。

A.适配器(Adapter)B.代理(Proxy)C.组合(Composite)D.修饰器(Decorator)

3.ArrayList list = new ArrayList(20);中的list对象扩充了几次__________。A.0

B.1

C.2

D.3

4.下面说法正确的是______________。(多选题)A.LinkedList 继承自List

B.AbstractSet继承自 Set D.WeakMap 继承自HashMap C.HashSet 继承自AbstractSet

5.0.6343的数据类型是______________。A.float

B.Float C.double

D.Double 6.下面代码片段中,执行后 i 和 j 的值是______________。int i = 1;int j;j = i++;A.1,1

7.函数重载是指_____________。

A.两个或两个以上的函数取相同的函数名,但形参的个数或类型不同。

B.两个以上的函数取相同的名字和具有相同的参数个数,但形参的类型可以不同。C.两个以上的函数名字不同,但形参的个数和类型相同。D.两个以上的函数取相同的函数名,并且函数的返回类型相同。

8.当方法遇到异常又不知如何处理时,下列哪种说法是正确的___________。A.捕获异常 B.抛出异常

C.声明异常

D.嵌套异常 B.1,2

C.2,1

D.2,2 9.关键字________可以用来为对象加互斥锁。A.transient B.static C.serialize

10.有以下方法的定义,该方法的返回类型为__________。ReturnType method(float x,int y){ return x += y;} A.float

B.short

D.synchronized

C.int

D.double 11.以下关于继承的叙述正确的是___________。A.在Java中类只允许单一继承 B.在Java中一个类只能实现一个接口

C.在Java中一个类不能同时继承一个类和实现一个接口 D.在Java中接口只允许单一继承

12.用java.util.concurrent里的类实现多线程编程,下列那些包可以实现可重入锁____。A.ReadWriteLock B.CallableLock C.ReentrantLock D.SyncLock

13.要从一个文件file.dat 中读出第10个字节到变量C中,以下哪种方法最合适________。

A.FileInputStream in = new FileInputStream(“file.dat”);in.skip(9);int c = in.read();B.FileInputStream in = new FileInputStream(“file.dat”);in.skip(10);in c = in.read();C.FileInputStream in = new FileInputStream(“file.dat”);int c = in.read();D.RandomAccessFile in = new RandomAccessFile(“file.dat”);in.skip(9);int c = in.readByte();

二、简答题

1.说明Overload 和 Override 的区别。Overloaded 的方法是否可以改变返回值的类型? 答:________________________________________________________________ ___________________________________________________________________ ___________________________________________________________________。

2.说明HashMap、Hashtable、ConcurrentHashMap 的区别,简述ConcurrentHashMap 的主要实现要点?

答:__________________________________________________________________ _____________________________________________________________________ _________________________________________________________________________________________________________________________________________。

3.Spring Cache 框架中@Cacheable,@CachePut,@CacheEvict,@CacheConfig 的用途分别是什么?

答:__________________________________________________________________ _____________________________________________________________________ _________________________________________________________________________________________________________________________________________。

4.Hibernate 的一级缓存和二级缓存的主要区别是什么?

答:__________________________________________________________________ _________________________________________________________________________________________________________________________________________。

5.MySql 的 explian 语句是做什么用途?

6.二级JAVA总结 篇六

对长度为n的线性表进行顺序排序,最坏情况先需要比较的次数为n。

高内聚低耦合有利于模块的独立性。

二叉树属于非线性结构。

算法具有可行性、确定性、有穷性和拥有足够的情报四个基本特征。

JAVA的反汇编命令是javap。

软件(程序)调试的任务是诊断和改正程序中的错误。

数据库应用系统中的核心问题是数据库设计。

在JAVA中,线程是抢占式的。

Object是所有类的根。

在软件开发中,需求分析阶段常使用的工具有数据流图(DFD)、数据字典(DD)、判断树和判断表。

关系数据库管理系统能实现的专门关系运算包括选择、投影、连接。

支持子程序调用的数据结构是栈。

init()方法用于初始化Applet ,start()方法用于激活Applet,paint()方法执行Applet的绘制功能。前序是根—左—右,中序是左—根—右,后序是左—右—根。

JAVA中,负责并发管理的机制是虚拟机。

JAVA中单精度常量以f或F结尾。

软件工程的理论和技术性研究的内容主要包括软件开发技术和软件工程管理。

相对于数据库系统,文件系统的主要缺陷有数据依赖、数据不一致性和冗余性。顺序存储结构的存储一定是连续的,链式存储结构的存储空间不一定是连续的。结构化程序设计的3种基本结构是顺序、选择、重复。

栈的特点是先进后出。队列的特点是先进先出。有序线性表既可以采用顺序存储结构,也可以采用链式存储结构。

数据库设计中反映用户对数据要求的模式是外模式。

对象具有如下特征:标识唯一性、分类型、多态性、封装性和模块独立性。

面向对象方法中,继承是指类之间共享属性和操作的机制。

类Pane默认的布局管理器是FlowLayout。

7.魏征总结历代用人经验 篇七

魏征完全认同唐太宗的看法,他进一步补充说:“天下未定,则专取其才,不考其行;丧乱既平,则非才行兼备不可用也。”魏征此言,一语道破古今明君用人的奥秘,可谓总结历代用人经验的概括性论断。

◎吴起杀妻求将惹非议

《资治通鉴》记载,“吴起者,卫人,仕于鲁。齐人伐鲁,鲁人欲以为将,起娶齐女为妻,鲁人疑之,起杀妻以求将,大破齐师。”为了当将领而不惜杀掉自己的妻子,吴起这种行径自然引起很多人的非议。

有人对鲁侯说:“起始事曾参,母死不奔丧,曾参绝之。今又杀妻以求为君将。起,残忍薄行人也!且以鲁国区区而有胜敌之名,则诸侯图鲁矣。”这里又把吴起“母死不奔丧”的另一劣行揭露出来,吴起被人们指责为“残忍薄行人”。吴起恐怕鲁侯怪罪他,听说魏文侯善用人,便跑到魏国谋求发展。

魏文侯当时以礼贤下士闻名于世,他问大臣李克:“吴起这个人怎么样?”李克说:“起贪而好色,然用兵,司马穰苴弗能过也。”

司马穰苴即田穰苴,是春秋时期齐国名将,李克认为吴起虽然贪财好色,但用兵连田穰苴都不能超过他。“于是文侯以为将,击秦,拔五城。”另外,吴起率兵守住西河,使秦兵不敢“东向”。

魏文侯死后,魏武侯继位,国相排挤吴起,吴起在魏国待不下去,又跑到楚国来。楚悼王听说吴起来了,十分高兴,马上任命吴起为楚国国相。吴起上任后,“南平百越,北却三晋,西伐秦,诸侯皆患楚之强。”但同时吴起也得罪了楚国的贵戚大臣,楚悼王一死,便把吴起杀了。

◎陈平曾经“盗嫂受金”

陈平这个人也很复杂,秦朝末年天下大乱,他先后追随魏不容和项羽,后来经魏无知推荐,才转到刘邦这边来,刘邦觉得这个人不错,便任命陈平为都尉,监督军中将领。刘邦诸将见陈平一来到就担任如此重要的职务,心中不平,议论纷纷。

周勃、灌婴等人对刘邦说:“陈平虽美如冠玉,其中未必有也。他曾居家时与其嫂通奸,同时反复无常,没有标准和原则,而且还受贿!”

刘邦听了这些话当然对陈平起了疑心,马上把魏无知叫来,责问他为什么推荐陈平这种“反覆乱臣”。魏无知辩解说:“臣所言者能也,陛下所问者行也。今有尾生、孝己之行,而无益胜负之数,陛下何暇用之乎!楚、汉相距,臣进奇谋之士,顾其计诚足以利国家不耳。盗嫂,受金,又何足疑乎!”

魏无知的一番话,说到了战乱时期用人的关键,那就是只取其才能,而不去追究其德行。所以尽管陈平有盗嫂受金之嫌,但只要他的计谋有利于国家,这个人就要用。

后来刘邦又找来陈平,要他解释为何要受贿,陈平说自己没钱做不成事,受贿的目的是想积累资金为国家办事,并非为了中饱私囊。刘邦这才知道错怪了陈平,于是拜陈平为护军中尉,监督军中所有军官,这样一来,诸将再也不敢对陈平闲言闲语了。

“丧乱既平,非才行兼备不可用”也是一条很重要的用人原则。秦始皇不明白这个道理,统一中国后起用赵高为中车府令,使赵高“教故亥决狱”,赵高有罪,蒙毅认为应判死刑,但秦始皇认为赵高“敏于事”,不仅赦其罪,还恢复了赵高的官职,埋下导致秦国灭亡的祸根。

唐玄宗晚年在用人方面也违背了这个原则,安禄山不听指挥打败仗,丞相张九龄认为“禄山失律丧师,于法不可不诛”,但唐玄宗“惜其骁勇”,赦了安禄山的罪,最终酿成安史之乱。

◎与其得小人,不若得愚人

对于德与才的关系,司马光有一段很精辟的论述。在《资治通鉴》第二篇史论中,司马光指出:德为才的统帅,决定着才的作用方向,才是德的支撑,影响德的作用和范围。德才兼备的“圣人”是用人的首选,其次是“德胜才”的“君子”,如果这两种人才都得不到,与其用“才胜德”的“小人”,不如用“才德兼亡”的“愚人”。

另外,司马光还指出领导考察人才的时候往往只注意才能而忽略德行,提醒人们自古以来“国之乱臣,家之败子”无一例外全都是“才有余而德不足”的“小人”,所以在用人时一定要全面考察一个人的才能与德行。

8.Java线程总结 篇八

首先要理解线程首先需要了解一些基本的东西,我们现在所使用的大多数操作系统都属于多任务,分时操作系统。正是由于这种操作系统的出现才有了多线程这个概念。我们使用的windows,linux就属于此列。什么是分时操作系统呢,通俗一点与就是可以同一时间执行多个程序的操作系统,在自己的电脑上面,你是不是一边听歌,一边聊天还一边看网页呢?但实际上,并不上cpu在同时执行这些程序,cpu只是将时间切割为时间片,然后将时间片分配给这些程序,获得时间片的程序开始执行,不等执行完毕,下个程序又获得时间片开始执行,这样多个程序轮流执行一段时间,由于现在cpu的高速计算能力,给人的感觉就像是多个程序在同时执行一样。

一般可以在同一时间内执行多个程序的操作系统都有进程的概念.一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间,一组系统资源.在进程概念中,每一个进程的内部数据和状态都是完全独立的.因此可以想像创建并执行一个进程的系统开像是比较大的,所以线程出现了。在java中,程序通过流控制来执行程序流,程序中单个顺序的流控制称为线程,多线程则指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务.多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行.(你可以将前面一句话的程序换成进程,进程是程序的一次执行过程,是系统运行程序的基本单位)

线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈.所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程也被称为轻负荷进程(light-weight process).一个进程中可以包含多个线程.多任务是指在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每个任务对应一个进程,同进程一样,一个线程也有从创建,运行到消亡的过程,称为线程的生命周期.用线程的状态(state)表明线程处在生命周期的哪个阶段.线程有创建,可运行,运行中,阻塞,死亡五中状态.通过线程的控制与调度可使线程在这几种状态间转化每个程序至少自动拥有一个线程,称为主线程.当程序加载到内存时,启动主线程.[线程的运行机制以及调度模型]

java中多线程就是一个类或一个程序执行或管理多个线程执行任务的能力,每个线程可以独立于其他线程而独立运行,当然也可以和其他线程协同运行,一个类控制着它的所有线程,可以决定哪个线程得到优先级,哪个线程可以访问其他类的资源,哪个线程开始执行,哪个保持休眠状态。下面是线程的机制图:

Page 1 of 16

线程的状态表示线程正在进行的活动以及在此时间段内所能完成的任务.线程有创建,可运行,运行中,阻塞,死亡五中状态.一个具有生命的线程,总是处于这五种状态之一: 1.创建状态

使用new运算符创建一个线程后,该线程仅仅是一个空对象,系统没有分配资源,称该线程处于创建状态(new thread)2.可运行状态

使用start()方法启动一个线程后,系统为该线程分配了除CPU外的所需资源,使该线程处于可运行状态(Runnable)3.运行中状态

Java运行系统通过调度选中一个Runnable的线程,使其占有CPU并转为运行中状态(Running).此时,系统真正执行线程的run()方法.4.阻塞状态

一个正在运行的线程因某种原因不能继续运行时,进入阻塞状态(Blocked)5.死亡状态

线程结束后是死亡状态(Dead)

同一时刻如果有多个线程处于可运行状态,则他们需要排队等待CPU资源.此时每个线程自动获得一个线程的优先级(priority),优先级的高低反映线程的重要或紧急程度.可运行状态的线程按优先级排队,线程调度依据优先级基础上的“先到先服务”原则.线程调度管理器负责线程排队和CPU在线程间的分配,并由线程调度算法进行调度.当线程调度管理器选种某个线程时,该线程获得CPU资源而进入运行状态.线程调度是先占式调度,即如果在当前线程执行过程中一个更高优先级的线程进入可运行状态,则这个线程立即被调度执行.先占式调度分为:独占式和分时方式.独占方式下,当前执行线程将一直执行下去,直 到执行完毕或由于某种原因主动放弃CPU,或CPU被一个更高优先级的线程抢占

分时方式下,当前运行线程获得一个时间片,时间到时,即使没有执行完也要让出

Page 2 of 16

CPU,进入可运行状态,等待下一个时间片的调度.系统选中其他可运行状态的线程执行

分时方式的系统使每个线程工作若干步,实现多线程同时运行

另外请注意下面的线程调度规则(如果有不理解,不急,往下看): ①如果两个或是两个以上的线程都修改一个对象,那么把执行修改的方法定义为被同步的(Synchronized),如果对象更新影响到只读方法,那么只度方法也应该定义为同步的

②如果一个线程必须等待一个对象状态发生变化,那么它应该在对象内部等待,而不是在外部等待,它可以调用一个被同步的方法,并让这个方法调用wait()③每当一个方法改变某个对象的状态的时候,它应该调用notifyAll()方法,这给等待队列的线程提供机会来看一看执行环境是否已发生改变

④记住wait(),notify(),notifyAll()方法属于Object类,而不是Thread类,仔细检查看是否每次执行wait()方法都有相应的notify()或notifyAll()方法,且它们作用与相同的对象 在java中每个类都有一个主线程,要执行一个程序,那么这个类当中一定要有main方法,这个man方法也就是java class中的主线程。你可以自己创建线程,有两种方法,一是继承Thread类,或是实现Runnable接口。一般情况下,最好避免继承,因为java中是单根继承,如果你选用继承,那么你的类就失去了弹性,当然也不能全然否定继承Thread,该方法编写简单,可以直接操作线程,适用于单重继承情况。至于选用那一种,具体情况具体分析。

eg.继承Thread

public class MyThread_1 extends Thread{ public void run(){ //some code } }

eg.实现Runnable接口

public class MyThread_2 implements Runnable { public void run(){ //some code } }

Page 3 of 16

当使用继承创建线程,这样启动线程:

new MyThread_1().start()

当使用实现接口创建线程,这样启动线程:

new Thread(new MyThread_2()).start()

注意,其实是创建一个线程实例,并以实现了Runnable接口的类为参数传入这个实例,当执行这个线程的时候,MyThread_2中run里面的代码将被执行。下面是完成的例子:

public class MyThread implements Runnable { public void run(){ System.out.println(“My Name is ”+Thread.currentThread().getName());} public static void main(String[] args){ new Thread(new MyThread()).start();} }

执行后将打印出: My Name is Thread-0

你也可以创建多个线程,像下面这样

new Thread(new MyThread()).start();new Thread(new MyThread()).start();new Thread(new MyThread()).start();

那么会打印出:

My Name is Thread-0 My Name is Thread-1

Page 4 of 16

My Name is Thread-2

看了上面的结果,你可能会认为线程的执行顺序是依次执行的,但是那只是一般情况,千万不要用以为是线程的执行机制;影响线程执行顺序的因素有几点:首先看看前面提到的优先级别

public class MyThread implements Runnable { public void run(){ System.out.println(“My Name is ”+Thread.currentThread().getName());} public static void main(String[] args){ Thread t1=new Thread(new MyThread());Thread t2=new Thread(new MyThread());Thread t3=new Thread(new MyThread());

t2.setPriority(Thread.MAX_PRIORITY);//赋予最高优先级

t1.start();t2.start();t3.start();} }

再看看结果:

My Name is Thread-1 My Name is Thread-0 My Name is Thread-2

Page 5 of 16

线程的优先级分为10级,分别用1到10的整数代表,默认情况是5。上面的t2.setPriority(Thread.MAX_PRIORITY)等价与t2.setPriority(10)

然后是线程程序本身的设计,比如使用sleep,yield,join,wait等方法(详情请看JDKDocument)

public class MyThread implements Runnable { public void run(){

try {

int sleepTime =(int)(Math.random()* 100);// 产生随机数字,Thread.currentThread().sleep(sleepTime);// 让其休眠一定时间,时间又上面sleepTime决定

// public static void sleep(long millis)throw InterruptedException

//(API)

System.out.println(Thread.currentThread().getName()+ “ 睡了 ”

+ sleepTime);

} catch(InterruptedException ie)

// 由于线程在休眠可能被中断,所以调用sleep方法的时候需要捕捉异常

Page 6 of 16

{

ie.printStackTrace();

} }

public static void main(String[] args){

Thread t1 = new Thread(new MyThread());

Thread t2 = new Thread(new MyThread());

Thread t3 = new Thread(new MyThread());

t1.start();

t2.start();

t3.start();} }

执行后观察其输出: Thread-0 睡了 11 Thread-2 睡了 48 Thread-1 睡了 69

上面的执行结果是随机的,再执行很可能出现不同的结果。由于上面我在run中添加了休眠语句,当线程休眠的时候就会让出cpu,cpu将会选择执行处于runnable状态中的其他线程,当然也可能出现这种情况,休眠的Thread立即进入了runnable状态,cpu再次执行它。[线程组概念] 线程是可以被组织的,java中存在线程组的概念,每个线程都是一个线程组的成员,线程组把多个线程集成为一个对象,通过线程组可以同时对其中的多个线程进行操作,如启动一个线程组的所有线程等.Java的线程组由java.lang包中的Thread——Group类实现.ThreadGroup类用来管理一组线程,包括:线程的数目,线程间的关系,线程正在执行的操作,以及线程将要启动或终止时间等.线程组还可以包含线程组.在Java的应用程序中,最高层的线程组是名位main的线程组,在main中还可以加入线程或

Page 7 of 16

线程组,在mian的子线程组中也可以加入线程和线程组,形成线程组和线程之间的树状继承关系。像上面创建的线程都是属于main这个线程组的。借用上面的例子,main里面可以这样写:

public static void main(String[] args){

/***************************************

* ThreadGroup(String name)ThreadGroup(ThreadGroup parent, String name)

***********************************/

ThreadGroup group1 = new ThreadGroup(“group1”);

ThreadGroup group2 = new ThreadGroup(group1, “group2”);

Thread t1 = new Thread(group2, new MyThread());

Thread t2 = new Thread(group2, new MyThread());

Thread t3 = new Thread(group2, new MyThread());

t1.start();

t2.start();

t3.start();} 线程组的嵌套,t1,t2,t3被加入group2,group2加入group1。

Page 8 of 16

另外一个比较多就是关于线程同步方面的,试想这样一种情况,你有一笔存款在银行,你在一家银行为你的账户存款,而你的妻子在另一家银行从这个账户提款,现在你有1000块在你的账户里面。你存入了1000,但是由于另一方也在对这笔存款进行操作,人家开始执行的时候只看到账户里面原来的1000元,当你的妻子提款1000元后,你妻子所在的银行就认为你的账户里面没有钱了,而你所在的银行却认为你还有2000元。看看下面的例子:

class BlankSaving // 储蓄账户 { private static int money = 10000;

public void add(int i){

money = money + i;

System.out.println(“Husband 向银行存入了 [¥” + i + “]”);}

public void get(int i){

money = money-i;

System.out.println(“Wife 向银行取走了 [¥” + i + “]”);

if(money < 0)

System.out.println(“余额不足!”);}

Page 9 of 16

public int showMoney(){

return money;} }

class Operater implements Runnable { String name;BlankSaving bs;

public Operater(BlankSaving b, String s){

name = s;

bs = b;

}

public static void oper(String name, BlankSaving bs){

if(name.equals(“husband”)){

try {

for(int i = 0;i < 10;i++){

Page 10 of 16

Thread.currentThread().sleep((int)(Math.random()* 300));

bs.add(1000);

}

} catch(InterruptedException e){

}

} else {

try {

for(int i = 0;i < 10;i++){

Thread.currentThread().sleep((int)(Math.random()* 300));

bs.get(1000);

}

} catch(InterruptedException e){

}

} }

public void run(){

oper(name, bs);}

Page 11 of 16

}

public class BankTest { public static void main(String[] args)throws InterruptedException {

BlankSaving bs = new BlankSaving();

Operater o1 = new Operater(bs, “husband”);

Operater o2 = new Operater(bs, “wife”);

Thread t1 = new Thread(o1);

Thread t2 = new Thread(o2);

t1.start();

t2.start();

Thread.currentThread().sleep(500);} }

下面是其中一次的执行结果:

---------first--------------Husband 向银行存入了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Husband 向银行存入了 [¥1000] Wife 向银行取走了 [¥1000] Husband 向银行存入了 [¥1000] Wife 向银行取走了 [¥1000] Husband 向银行存入了 [¥1000] Wife 向银行取走了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000]

Page 12 of 16

Wife 向银行取走了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Husband 向银行存入了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Husband 向银行存入了 [¥1000]

看到了吗,这可不是正确的需求,在husband还没有结束操作的时候,wife就插了进来,这样很可能导致意外的结果。解决办法很简单,就是将对数据进行操作方法声明为synchronized,当方法被该关键字声明后,也就意味着,如果这个数据被加锁,只有一个对象得到这个数据的锁的时候该对象才能对这个数据进行操作。也就是当你存款的时候,这笔账户在其他地方是不能进行操作的,只有你存款完毕,银行管理人员将账户解锁,其他人才能对这个账户进行操作。

修改public static void oper(String name,BlankSaving bs)为public static void oper(String name,BlankSaving bs),再看看结果:

Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Husband 向银行存入了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000] Wife 向银行取走了 [¥1000]

当丈夫完成操作后,妻子才开始执行操作,这样的话,对共享对象的操作就不会有问题了。

[wait and notify] 你可以利用这两个方法很好的控制线程的执行流程,当线程调用wait方法后,线

Page 13 of 16

程将被挂起,直到被另一线程唤醒(notify)或则是如果wait方法指定有时间得话,在没有被唤醒的情况下,指定时间时间过后也将自动被唤醒。但是要注意一定,被唤醒并不是指马上执行,而是从组塞状态变为可运行状态,其是否运行还要看cpu的调度。事例代码:

class MyThread_1 extends Thread {

Object lock;

public MyThread_1(Object o){

lock = o;}

public void run(){

try {

synchronized(lock){

System.out.println(“Enter Thread_1 and wait”);

lock.wait();

System.out.println(“be notified”);

}

} catch(InterruptedException e){

} }

Page 14 of 16

}

class MyThread_2 extends Thread { Object lock;

public MyThread_2(Object o){

lock = o;}

public void run(){

synchronized(lock){

System.out.println(“Enter Thread_2 and notify”);

lock.notify();

} } }

public class MyThread { public static void main(String[] args){

int[] in = new int[0];// notice

MyThread_1 t1 = new MyThread_1(in);

Page 15 of 16

MyThread_2 t2 = new MyThread_2(in);

t1.start();

t2.start();} }

执行结果如下:

Enter Thread_1 and wait Enter Thread_2 and notify Thread_1 be notified

可能你注意到了在使用wait and notify方法得时候我使用了synchronized块来包装这两个方法,这是由于调用这两个方法的时候线程必须获得锁,也就是上面代码中的lock[],如果你不用synchronized包装这两个方法的得话,又或则锁不一是同一把,比如在MyThread_2中synchronized(lock)改为synchronized(this),那么执行这个程序的时候将会抛出java.lang.IllegalMonitorStateException执行期异常。另外wait and notify方法是Object中的,并不在Thread这个类中。最后你可能注意到了这点:int[] in=new int[0];为什么不是创建new Object而是一个0长度的数组,那是因为在java中创建一个0长度的数组来充当锁更加高效。

上一篇:金话筒主持大赛决赛流程下一篇:公司内部会议管理办法