欢迎大家来到测试人生,在你休息的时候你可以畅所欲言,空间里也许有些资料可以帮助到你,来吧,朋友,测试人生欢迎你!!!!

发布新日志

  • 从印度软件项目管理谈我国软件质量保障

    2008-10-22 11:41:33

    计算机和通信技术的迅速发展,特别是Internet技术的发展与普及,为企业内部、企业与外部提供了快速、准确、可靠的信息交流渠道。信息化企业运作管理系统已成为企事业单位参与全球市场竞争的必备支持系统。正是由于这样的市场需求与技术发展现状,为我国的IT行业带来了空前发展的机遇,特别是软件行业。软件企业能否抓住这样一个难得的发展机会需要多方面的努力,其中软件质量保障在其发展过程中占有重要的位置。
    众所周知,印度已成为世界上软件业增长最快的国家,目前每年软件业产值达数十亿美元,并且还在以每年30%~50%的速度增长。比较我国和印度的软件产业,就不难发现:中国拥有巨大的软件市场和世界公认的软件开发资源,在基础研究和对技术前瞻性的把握上,也有自己的优势,就整体社会经济环境而言也优于印度。此外,中国的软件开发人员费用比较低廉,仅是世界市场的1/3左右。虽然中国人并不缺乏软件开发的天赋,但是在越来越强调规模化经营的今天,先天不足的管理痼疾使我们举步维艰,难以摆脱小作坊式的软件开发模式。而印度软件业从一开始就立足于为美国软件企业服务,并遵循其软件开发的管理模式,与国际标准接轨。
    管理上的问题不能得到彻底的解决,软件的质量保障就无从谈起。笔者最近在与印度一家通过了CMM4级评估的软件公司(以下简称A公司)进行合作的过程中,较为详细地了解了他们有关项目管理的一些详细情况,更深刻地感受到了项目管理的规范化与企业软件质量保障之间的密切关系。下面想着重从软件企业的构架,软件项目计划、项目管理、项目经理的职责等方面对印度软件的项目管理及我国软件质量保障应注意的问题进行一些经验总结,供业内人士参考。
    1.软件企业的组织结构
    (1)A公司结构
    图1是A公司的组织结构图,同国内公司差异较大的部门有QA、SSG和人力资源部门。

    图1
    * A公司中,QA(Quality Assure)部门与研发部门独立,负责监督流程的执行。QA同时负责领导与研发部门组成的联合工作组,制定公司流程。
    * SSG(System Support Group)类似我们的IT部门,负责公司所有计算机软件和硬件资源的分配和管理。所有的办公环境和开发/实验室环境由SSG负责安装和维护,计算机资源属于SSG,由各个项目向SSG提出需求,项目结束后,设备需要交还给SSG。个人和项目组没有固定的软件和硬件资源。SSG是与研发平行的部门。
    * 人力资源部门负责公司的人力资源管理,并维护员工的技能数据库。项目开始时,项目组向人力资源申请人力,向SSG申请计算机硬件和软件。项目结束时需要释放计算机资源给SSG,释放人力资源到人力资源池,并同时更新员工的技能数据库。研发部门的人力资源由研发总负责人和其助手分配(类似我国各公司的人力资源部)。
    (2)项目组结构
    1) A公司对项目组进行独立核算,项目具体负责人为PC(Project Coordinator),负责项目计划和执行,对项目具体成员进行分工。在每个阶段的结束会议上(如概要设计结束),PC要接受QC(Quality Coordinator)的审查。除了PC与QC的接口外,所有其他外部接口都由EM(Engineer Manager)完成,EM负责与客户打交道,向SSG、人力资源要求资源,与其他项目组协调进度。
    2) 汇报关系为:
    Team Member->Team Leader->PC->EM->研发总负责人。
    3) 印度工程师分为7级,半年一次考评,即半年有一次升级机会。
    1级:Software Engineer,刚毕业的本科生和研究生。
    2级:Senior Software Engineer。
    3级:Project Leader。
    4级:Project Manager。
    5级:Senior Project Manager。
    3级可以成为PC,4级可以成为EM。刚开始平均2年升一级,越往后升职越慢。
    A公司规定,一人最多可以同时兼任两个项目的PC,EM管理的项目没有限制。
    A公司通常的项目组为4到5人,最多不超过10人。
    以上是A公司(同时也是印度大多数规范化的软件公司)的组织结构和项目组结构。可以看出,A公司的组织结构非常清晰,各个部门分类非常细,任务明确,软件生产的每一个步骤都有专门的部门、专门的人员负责,从最基础的开发人员到负责统领全局的总经理,层层管理,沟通渠道畅通。而在我国,管理的不规范往往首先体现在公司的组织结构上,集中表现为部门的缺失和管理的交叉上。我国的软件公司,大部分规模较小,开发人员超过100人的公司很少。在印度,软件公司无论大小,都是“麻雀虽小,五脏俱全”,绝不会因为公司的规模大小而改变合理的组织结构。因此笔者认为,国内的软件企业要想有效地保障产品质量,首先就要在构架合理的组织结构上下功夫,这就如同盖高楼首先要打好地基一样,地基不打牢,结构不合理,其他方面再下功夫也是徒劳。有人说,因为国内软件企业规模小,所以造成结构设置的欠缺,但笔者认为恰恰是因为没有建立一个规范化的组织结构,才会使软件产品质量不保,进而严重影响了企业的发展扩大。
    2.项目计划
    凡事预则立,不预则废。这里的“预”就是指计划。对于软件企业,计划的重要性是不言而喻的。让我们先看看A公司的项目计划是如何制定的:在A公司,项目开始之前必须先估计项目的规模(以代码行数来衡量);然后制定项目计划。通常时间为2~3周,已知的最长有5周。EM负责制定项目 EWP(Engineer Work Paper),其中定义了项目需要的人力和计算机资源,由相关部门同意,并报研发总负责人批准后才能开始项目。
    项目的正式开始时间由项目组的Kickoff Meeting算起,Closeout Meeting结束。
    大概很多人都听过这样一句话:“计划赶不上变化”。这种“变化”对某些行业而言也许并不会产生太大的影响,但对于软件企业而言,却会给软件产品的质量保证带来严重的负面影响。为什么会造成这种“计划赶不上变化”的现象?究其原因,笔者认为主要是因为对计划的重视程度不够,计划过于笼统、粗糙导致可执行性太差,再加上一些人为因素的影响,必然会产生这样的后果。
    如果我们的软件企业都能像A公司这样,在作计划时能考虑到每一个细节,不是仓促做出决定,而是由所有的相关部门共同对产品计划进行反复研究、制定、讨论、修改,最终形成一套系统、严密、具有很强的可执行性的计划。计划一旦形成,就严格按照计划去执行,而不受某个人、某件事的影响,那么就不仅能够减少大量资源的浪费,产品的质量也得到了保障。
    因此,对计划的高度重视、周密制定、严格执行是企业有效保障产品质量的一个重要环节。
    3.项目管理
    当企业构架了合理的组织结构并制定了缜密的计划后,就进入了产品的开发阶段。在这个阶段中,项目管理起了重要作用,它所涉及的环节相当具体复杂,下面先介绍一下A公司在项目管理上的具体细节:
    (1)开发阶段和项目周期
    开发阶段比较明显,注重各阶段应完成的功能,对本阶段应完成的工作不能留到下一阶段。
    (2)流程
    * A公司对流程比对项目更重视。
    * 软件开发流程非常规范和系统化,其流程的可执行性很高,并且能在实践过程中不断改进。A公司的流程已覆盖到了一个项目研发的所有方面,包括从最开始的意向到最后软件的版本发布(release),都有相应的流程规定,基本上已形成一种工业化的软件开发。
    * 人和流程是保证项目成功的两个最关键因素。由好的人按好的流程进行项目开发,才能最大限度地保证项目的成功。一个好的流程可以保证差的人做出来的东西不至于太差,但不能确保做出精品。通过流程可以实现一种规范化、流水线化、工业化的软件开发。
    (3)计划
    1) 计划详细、周到。
    2) 流程中明确定义开发阶段。
    3) 每个阶段都列出了该阶段的各项活动,并详细描述每项活动的属性:
    * 进入条件,输入;
    * 验证方法;
    * 结束条件,输出。
    4)每个阶段结束都要召开阶段结束会议。前一个阶段结束才能进入下一阶段。
    5)计划中每个活动都比较具体,每个活动的时间以天(半天)为单位。计划包括了开展质量控制活动的时间。
    (4)Review
    按印度公司流程,一般把Review和测试作为保证软件质量两个主要手段。测试的重要性就不需说明了,而Review则是一个非常简单有效并能尽早发现软件中错误的方法,可以说,任何交付物都要经Review后才能进行基线化。目前A公司有很详细全面、可执行性很高的Review流程和各种交付物的Review Checklist。
    在印度软件企业,现有这么一句口号:凡事有计划,凡事必review。
    (5)QA
    QC(质量经理)作为质量保证部门(SQA)的代表,监督和保证项目的进展遵循QMS各项流程和模板,并且收集项目中发现的一些问题和解决方法以优化流程。
    (6)度量数据
    CMM中比较强调用数据说话,对项目过程中基本上所有的数据都会有记录,最后把收集的数据提交质量保证部门进行分析,以改进流程。A公司的项目经理和质量经理很重视项目中的数据收集,包括各种Review数据、测试数据以及项目组员每天的活动数据等。项目经理也要维护一个项目档案,在这个项目档案中可以说包含了项目开发过程中所有的产出、开发活动、管理活动等的记录。可以这么说,有了这个项目档案,你就可以完全了解这个项目的开发过程。
    (7)团队精神
    印度公司都比较强调团队精神、合作精神,应该说,其流程本质上就要求员工之间的互相协调和理解。相对而言,印度员工的合作精神和协调精神都比我国员工要好得多。
    (8)培训
    印度公司都比较强调培训,一般有专门的培训部门进行协调。在新员工进入公司后都会有公司流程和其他一些公司普遍章程的培训,以保证员工对流程的理解和执行。对于具体项目,项目经理在制定项目计划时就会在项目计划中提出所有的培训需求,包括技术上的培训和其他所需的培训。
    (9)配置管理
    在项目正式开展前,项目经理就要制定配置管理计划,并且指定配置管理员建立起配置管理库,按配置流程严格进行配置管理。在配置流程中也详细提供了对更改的控制,没有经过批准的更改请求是绝对不能进行的。
    (10)记录
    记录及时、充分、比较准确。这些记录包括:重要的邮件、会议纪要、审核记录、缺陷报告、测试报告。
    1)与客户和其他项目组的所有往来必须邮件记录。
    2)对所有的活动都有一个跟踪落实的过程,比如对所有的Review记录和更改请求都会有一个状态标识,标识其当前状态,通过跟踪其状态来监督其落实。
    3)对所有的活动,包括对文档和代码的更改都会有一个历史记录。
    4)记录比较准确、比较客观。
    5)许多记录都是通过定量的数值记录,强调以数据说话(CMM4级的重点就是量化管理)。
    以上是A公司在项目管理中所涉及到的一些主要环节,很值得国内的软件企业在制定项目管理规划时借鉴。除此之外,我国的软件企业在产品开发管理的过程中,还易出现以下几个方面的问题:
    1)需求说明差─需求不清楚、不完整、太概括、或者不可测试,都会造成问题。
    2)不切实际的时间表─如果在很短的时间里要求做许多事,出现错误是不可避免的。
    3)测试不充分─只能根据客户意见或系统崩溃来判断系统的质量。
    4)不断增加功能─在开发正在进行过程中要求增加许多新的功能。这是常见的问题。
    5)交流问题─如果开发人员对客户的要求不了解,或者客户由不恰当的期望,必然会导致错误。
    这些问题的出现,将会对软件质量的保证产生不良影响,针对上述问题并结合A公司在项目管理方面的经验,笔者提出一些相应的解决方法,以供参考:
    1)可靠的需求─应当有一个经各方一致同意的、清楚的、完整的、详细的、整体的、可实现的、可测试的需求。为帮助确定需求,可使用模型 (prototypes)。
    2)合理的时间表——为计划、设计、测试、改错、再测试、变更、以及编制文档留出足够的时间。不应使用突击的办法来完成项目。
    3)适当测试─尽早开始测试;每次改错或变更后,都应重新测试。项目计划中要为测试和改错留出足够时间。
    4)尽可能坚持最初的需求─一旦开发工作开始,要准备防止修改需求和新增功能,要说明这样做的后果。如果必须进行变更,必须在时间表上有相应的反映。如果可能,在设计阶段使用快速的模型,以便使客户了解将会得到的东西。这将会使他们对他们的需求有较高的信心,减少以后的变更。
    5)沟通——在适当时机进行预排和检查;充分利用团组通信工具—电子邮件、群件(groupware)、网络故障跟踪工具、变更管理工具、以及因特网的功能。要确保文件是可用的和最新的。优选电子版文档,避免纸介质文档:进行远距离联合作业及协作;尽早使用模型,使客户的预想表达清楚。
    4.PC(项目经理)
    项目经理是项目成败的关键人物,其对项目的成败负主要责任。因此在这里将项目经理的有关内容单独提出,以A公司为例详细说明PC在整个产品研发过程中所扮演的角色,希望能对国内软件企业的项目经理有所启示。
    (1)在A公司,按流程在一个项目正式开展之前,项目经理需要完成:
    * 项目计划(Project Plan):在此描述整个项目所应完成的交付物、项目时间表、培训需求、资源需求、质量保证计划以及过程和交付物的定量质量目标等。
    * 项目配置管理计划(Project Configuration Plan):在此指定配置管理员,描述项目配置项列表、配置管理库、版本管理计划等等。
    *项目过程手册(Process Handbook):在此描述本项目所采取的裁剪后的生命周期模型和流程。
    (2)在项目开发过程中,项目经理需非常了解项目进度,进行工作任务细化、具体计划和安排项目成员工作任务等工作。对突发事件项目经理需能及时合理地进行协调。
    (3)总的说来,PC安排工作有这么几个特点:
    a.PC对软件开发具有丰富的经验,了解软件开发的普遍流程,了解各个阶段所需完成的工作,这是安排好项目组成员工作的前提,在A公司对PC的整体素质要求非常高。
    b.在项目正式开展前,PC准备项目计划文档,在项目计划中包含了项目进度时间表,但此时间表比较粗,只能给出各个阶段和各个子阶段的起始结束日期。对各个阶段和各个子阶段的详细工作安排和各项工作责任人只能在项目开展工程中根据项目实际情况进行安排,一般是在每周项目组例会上进行本周详细工作安排。
    c.PC对工作安排往往精确到天,有时甚至精确到小时,要做到这一点,需要:
    * PC对本项目进展非常了解。了解渠道通常是每周组员的状态报告和直接与组员接触了解,这也需项目组成员能如实汇报工作。
    * 对现阶段或本周所需完成的工作非常了解。知道现在该做什么,并且能把各项工作进行合理细致地划分,因为各个分解的工作比较细致,因此能相对精确地评估出这些工作完成所需的时间。
    * PC对项目组员的能力比较了解,安排工作时能做到有的放矢。当安排的员工对工作不熟悉时,会指定相应的组员进行协助。
    * PC对组员的工作安排都比较细致饱满。一般不会出现有些员工有事干,有些员工没事干的情况,当出现这种情况或员工提前完成工作时,PC就会进行相应的协调。
    d.PC在项目组例会上的工作安排一般只限于本周或甚至是过后的二、三天,一般不会太长,对长时间工作的安排容易失去精确并且不易控制。相对而言,短时间的工作安排就比较精确而且容易控制,并且能不断根据完成的工作进行调整。当然,这就要求PC能根据项目计划中的项目时间表进行整体进度的把握。
    e.项目组例会一般一周一次(时间不能太长),但必要时(如组员工作已完成或其他事情),也可在中途召开项目会议进行工作安排,一般时间都比较短(十几分钟左右,一般不超过半小时,以免浪费时间),总之,当PC觉得需要时,就会召开项目会议。
    f.当项目组出现意外事件或影响项目团结的事件时,PC能及时合理协调,解决项目组内的不和谐气氛。
    g.PC善于鼓励手下,发挥员工的潜能,PC往往会赞扬很好地完成了工作的组员。
    从上面可以看出,对PC的能力(包括技术和管理能力)要求是非常高的,我国的软件企业往往只重视PC的技术能力,但事实上,一个只精通技术的人往往不能成为一个合格的领导者, 笔者认为对PC而言,首先要求他能够比他的下属看得更远一步,顺利时不盲目乐观,遇到挫折时不茫然失措,使整个团队始终保持高昂的士气。
    总结   
    以上结合印度软件项目管理的经验总结了一些我国软件质量保障应注意的问题。曾有人提出:这样一味地学习模仿,民族软件工业没有多大希望。但笔者认为,在这个问题上不妨采取“拿来主义”的办法,对于好的,事实证明是成功的经验,首先是“占有”,然后才是“挑选”和“创新”。如果能把印度的管理经验真正领会并付诸实践,相信对我们的民族软件工业一定会起到积极的推动作用.

  • 性能测试指标介绍

    2008-10-22 11:40:13

    TPC-C

    作为一家非盈利性机构,事务处理性能委员会(TPC)负责定义诸如TPC-C、TPC-H和TPC-W基准测试之类的事务处理与数据库性能基准测试,并依据这些基准测试项目发布客观性能数据。TPC基准测试采用极为严格的运行环境,并且必须在独立审计机构监督下进行。委员会成员包括大多数主要数据库产品厂商以及服务器硬件系统供应商。

    相关企业参与TPC基准测试以期在规定运行环境中获得客观性能验证,并通过应用测试过程中所使用的技术开发出更加强健且更具伸缩性的软件产品及硬件设备。

    TPC-C是一种旨在衡量联机事务处理(OLTP)系统性能与可伸缩性的行业标准基准测试项目。这种基准测试项目将对包括查询、更新及队列式小批量事务在内的广泛数据库功能进行测试。许多IT专业人员将TPC-C视为衡量“真实”OLTP系统性能的有效指示器。

    TPC-C基准测试针对一种模拟订单录入与销售环境测量每分钟商业事务(tpmC)吞吐量。特别值得一提的是,它将专门测量系统在同时执行其它四种事务类型(如支付、订单状态更新、交付及证券级变更)时每分钟所生成的新增订单事务数量。独立审计机构将负责对基准测试结果进行公证,同时,TPC将出据一份全面彻底的测试报告。这份测试报告可以从TPC Web站点(http://www.tpc.org)上获得。

    tpmC定义: TPC-C的吞吐量,按有效TPC-C配置期间每分钟处理的平均交易次数测量,至少要运行12分钟。

    1.TPC-C规范概要

    TPC-C是专门针对联机交易处理系统(OLTP系统)的,一般情况下我们也把这类系统称为业务处理系统。

    TPC-C测试规范中模拟了一个比较复杂并具有代表意义的OLTP应用环境:假设有一个大型商品批发商,它拥有若干个分布在不同区域的商品库;每个仓库负责为10个销售点供货;每个销售点为3000个客户提供服务;每个客户平均一个订单有10项产品;所有订单中约1%的产品在其直接所属的仓库中没有存货,需要由其他区域的仓库来供货。

    该系统需要处理的交易为以下几种:

    •   New-Order:客户输入一笔新的订货交易;

    •   Payment:更新客户账户余额以反映其支付状况;

    •   Delivery:发货(模拟批处理交易);

    •   Order-Status:查询客户最近交易的状态;

    •   Stock-Level:查询仓库库存状况,以便能够及时补货。

    对于前四种类型的交易,要求响应时间在5秒以内;对于库存状况查询交易,要求响应时间在20秒以内。

    逻辑结构图:

    逻辑结构图:

    流程图:

    流程图:

    2.评测指标

    TPC-C测试规范经过两年的研制,于1992年7月发布。几乎所有在OLTP市场提供软硬件平台的厂商都发布了相应的TPC-C测试结果,随着计算机技术的不断发展,这些测试结果也在不断刷新。

    TPC-C的测试结果主要有两个指标:

    ● 流量指标(Throughput,简称tpmC)

    按照TPC的定义,流量指标描述了系统在执行Payment、Order-status、Delivery、Stock-Level这四种交易的同时,每分钟可以处理多少个New-Order交易。所有交易的响应时间必须满足TPC-C测试规范的要求。

    流量指标值越大越好!

    ● 性价比(Price/Performance,简称Price/tpmC)

    即测试系统价格(指在美国的报价)与流量指标的比值。

    性价比越小越好!

    3.结果发布

    各厂商的TPC-C测试结果都按TPC组织规定的两种形式发布:测试结果概要(Executive Summary)和详细测试报告(Full Disclosure Report)。测试结果概要中描述了主要的测试指标、测试环境示意图以及完整的系统配置与报价,而详细测试报告中除了包含上述内容外,还详细说明了整个测试环境的设置与测试过程。

    P690 tpmC测试值:76,389,839.00

    $/tpmC:831.00

    美国美金报价:6,349,223.0

    CPU数:32

    数据库:IBM DB2 UDB 8.1

    操作系统:AIX 5L V5.2

    中间件:TUXEDO 8.0

    测试日期:2003.6.30

    P690 TPC-C测试的配置:

    1.  后台:1 x eServer pSeries 690 with 32 x 1.7GHz POWER4+ processors with 128MB L3 cache per MCM (total of four MCMs), 512GB memory

    2.  前端:30 x eServer pSeries 630 Model 6E4 each with 4 x 1.0GHz POWER4 CPUs with 32MB L3 cache, 16GB memory

    SPECweb:

    SPECweb96: 在SPECweb96基准测试程序上实现的每秒钟超文本传输协议(HTTP)操作最多次数,响应时间无明显退化。

    SPECweb99: 接入数,网络服务器可用预先确定的工作量支持的同时接入数。SPECweb99检测设备模拟客户通过慢Internet联接,向网络服务器发送HTTP工作量请求。

    SPECweb99 测试Web服务器运行状况

    SPECweb99 是由标准性能评估组织(SPEC)开发的Web服务器基准测试。它测量满足特定吞吐量和客户请求响应速率要求的WEB服务器的最大并发连接数量。并发连接的合计波特率在320 Kbps到400Kbps范围内,则满足相应规范。

    SPECweb99 在一台称为主客户端的机器上运行,这台机器上包含有允许用户加载特定负载请求的配置文件。主客户端也要处理在客户端和服务器或测试中的系统(SUT)之间的传输协调问题。客户端通过许多子进程/线程生成独立HTTP请求流,仿真足够的负载发送给SUT。图二表示客户端/服务器的层次关系。

    图2. 典型 SPECweb99 实验设置

    图:典型的SPECweb99实验环境

    在这个测试中,客户端向测试中的服务器发送请求数据。测试规范要求客户端和服务器之间的连接不能使用片段大小大于1460比特的TCP协议。因此,每一个客户端读取1460比特或更少数据块的响应。

    测试中使用两种类型的负载量:

    静态负载. 静态负载具有四种类型的文件。最小的文件的增幅为0.1KB,第二种文件类型的增幅为1KB,最后两种类型的文件的增幅为10KB和100KB。每一个目录包含每种类型9个文件共36个文件。

    目标请求的文件类型在各类型中分散使用。在每一类中的9个文件中又进行二次分布。最终目标文件混合为:

    35%的请求文件小于1 KB

    50%的请求文件小于10 KB

    14%的请求文件小于100 KB,但是大于或等于10 KB

    1%的请求文件小于1000 KB,但是大于或等于100 KB

    动态负载.动态负载是基于广告和用户注册。共有四种在SPECweb99中使用的请求内容类型,分别是标准动态取操作、动态随机取操作、动态发送操作和客户图形接口动态取操作。标准动态取操作和客户图形接口动态取操作表现web服务器的简单广告轮转特性。带有广告轮转的动态取操作追踪用户和用户选择,所以广告可以由不同的方式来定制。最终,动态发布实施一个用户注册在相应的网站上。

    P690 SPECweb99测试值:21,000

    Web服务器:Zeus 4.0

    操作系统:AIX 5L V5.1 (64-bit)

    CPU数:16

    测试日期:2001-10-1

    测试配置:16 x 1.3GHz POWER-4 Processors w/1440KB unified on chip L2 cache, 192GB memory, 32 x 32 IBM Gigabit Ethernet-SX PCI controllers, 32 x Gigabit Ethernet network (1 Gigabit/sec  ), 96 x Clients (4 x 375MHz POWER3-II, RS/6000 44P-270), Requested Connections = 21000, Max Fileset Size = 67319.6MB

    P650 SPECweb99测试值:12,400

    Web服务器:Zeus 4.1r3

    操作系统:AIX 5L V5.2 (64-bit)

    CPU数:8

    测试日期:2002-10-1

    测试配置:8 x 1.45GHz POWER4+ processors w/1.5MB(I+D) unified on chip L2 cache, 32MB unified off chip/SCM L3 cache, 64GB memory, 8 x Gigabit Ethernet-SX PCI-X controllers, 8 x Gigabit Ethernet network (1 Gigabit/sec ), 48 x Clients (6 x 668MHz RS64-IV, pSeries 620 Model 6F1), Requested Connections = 12400, Max Fileset Size = 39801.28MB

    p630 SPECweb99测试值:6,895

    Web服务器:Zeus 4.2r1

    操作系统:AIX 5L V5.2(64-bit)

    CPU数:4

    测试日期:2003-2-1

    测试配置:4 x 1450MHz POWER4+ Processors w/1536KB(I+D) unified on chip L2 cache, 8MB unified (off chip)/SCM L3 cache, 32GB memory, 4 x Gigabit Ethernet-SX PCI-X controllers, 4 x Gigabit Ethernet networks (1 Gigabit/sec ), 24 x Clients (4 x 375MHz POWER3-II, pSeries 640 Model B80), Requested Connections = 6900, Max Fileset Size = 22199.12MB

    NotesBench:

    NotesBench是测试各种不同Lotus Notes方面的驱动程序。目的是执行自定义工作量教本中的命令,模拟客户机的操作。NotesBench测试“仅测试邮件”和“测试邮件和数据库”。所有已经公布的IBM结果均为“仅测试邮件工作量”。

    p680 NotesBench测试值:150,197

    用户数:108,000

    平均反应时间:0.584秒

    Domino服务器版本:5.06a

    操作系统:AIX 4.3.3

    CPU数:4

    测试日期:2001.11.20

    测试配置:IBM eServer pSeries 680 (24*RS64 IV/600MHz; 96GB RAM, 30 Partitions)

  • 被收容者孙志刚之死(二)

    2008-10-22 11:01:34

    孙志刚该被收容吗?

    有工作单位,有正常居所,有身份证,只缺一张暂住证

    接到死者家属提供的材料以后,记者走访了孙志刚临死前3天呆过的那3个地方。

    黄村街派出所拒绝接受采访,称必须要有分局秘书科的批准。记者赶到天河分局,在分局门外与秘书科的同志通了电话,秘书科表示,必须要有市公安局宣传处新闻科的批准。记者随后与新闻科的同志取得了联系,被告知必须先传真采访提纲。记者随后传了采访提纲给对方,但截至发稿时为止,尚没有得到答复。

    广州市收容遣送中转站的一位副站长同样表示,没有上级机关的批准,他无法接受采访。记者随后来到广州市民政局事务处,该处处长谢志棠接待了记者。

    谢志棠说,他知道孙志刚死亡一事。“收容站的工作人员都是公务人员,打人是会被开除的,而且收容站有监控录像”,谢志棠说,孙为什么被打他不清楚,但绝对不会是在收容站里被打的。在发现孙志刚不适以后,他们就立刻把孙送进了医院。

    “我有百分之九十九点八的把握可以保证,收容站里是不会打人的”,谢志棠说。谢志棠还说,孙被送到收容站的时间并不长。

    与广州市收容遣送中转站一样,收治孙志刚的广州市脑科医院的医教科负责人也表示,孙的外伤绝对不是在住院期间发生的。这名负责人介绍,医院内安装有录像监控装置,有专人负责监控,一旦发现打架斗殴,会立即制止。记者要求查看录像记录,该负责人表示,将等待公安部门调查,在调查结果没出来前,他们不会提供录像资料给记者。

    孙志刚是被谁打死的?

    民政局认为收容站不可能打人,救治站否认孙的外伤发生在住院期间,黄村街派出所拒绝接受采访

    在离开收容站前往医院时,孙志刚曾填写了一张《离站征询意见表》,他写的是:满意!感谢!感谢!

    现在已经无从知晓孙志刚当时的心情,也不知道他为什么要连写两个“感谢”,是在感谢自己被收容吗?

    记者在翻阅有关管理条例并征询专业人员以后,才发现,孙志刚似乎并不属于应该被收容的对象。

    在广东省人民代表大会常务委员会2002年2月23日通过并已于同年4月1日实施的《广东省收容遣送管理规定》中,明确规定,“在本省城市中流浪乞讨、生活无着人员的收容遣送管理工作适用本规定”。

    黄村街派出所的一位侦查员在填写审查人意见时写道:“根据《广东省收容遣送管理规定》第九条第6款的规定,建议收容遣送。”

    这一款是这样规定的:

    第九条 有下列情形之一的人员,应当予以收容:

    ……(六)无合法证件且无正常居所、无正当生活来源而流落街头的;

    《规定》中还明确规定:“有合法证件、正常居所、正当生活来源,但未随身携带证件的,经本人说明情况并查证属实,收容部门不得收容”。

    孙志刚有工作单位,不能说是“无正当生活来源”;住在朋友家中,不能说是“无正常居所”;有身份证,也不能说是“无合法证件”。

    在派出所的询问笔录中,很清楚记录着孙本人的身份证号码,但是在黄村街派出所填写的表格中,就变成了“无固定住所,无生活来源,无有效证件”。

    孙志刚本人缺的,仅仅是一个暂住证。但是记者在任何一条法规中,都没查到“缺了暂住证就要收容”的规定。记者为此电话采访广州省人大法工委办公室,得到了明确的答复:仅缺暂住证,是不能收容的。

    能够按广州市关于“三无”流浪乞讨人员管理的有关规定处理的,仅仅是不按规定申领流动人员临时登记证,或者流动人员临时登记证过期后“未就业仍在本市暂住的”人员。

    但不知为什么,在黄村街派出所的询问笔录中,在“你现在有无固定住所在何处”和“你现在广州的生活来源靠什么,有何证明”这两个问题下面,也都注明是“无”。

    成先生已经向记者证实孙志刚确实是住在他处的,此外,记者也看到了服装公司开出的书面证明,证明孙是在“2003年2月24日到我公司上班,任平面设计师一职,任职期间表现良好,为人正直,确是我……服装有限公司的工作人员”。

    为何在有孙志刚签名的笔录中,他却变成了无“生活来源”呢?这现在也是个未解之谜,民政局的谢处长对此也感到很困惑,“他一个大学生,智商不会低,怎么会说自己没有工作呢?”

    于是,按照询问笔录上的情况,孙志刚变成了“三无”人员,派出所负责人签名“同意收容遣送”,市(区)公安机关也同意收容审查,于是,孙志刚被收容了,最后,他死了。

    孙志刚的意外死亡令他的家人好友、同学老师都不胜悲伤,在他们眼中:孙志刚是一个很好的人,很有才华,有些偏激,有些固执。孙的弟弟说,“他社会经验不多,就是学习和干工作,比较喜欢讲大道理。”

    孙志刚的同班同学李小玲说,搞艺术的人都有自己的个性,孙志刚很有自己的想法,不过遇事爱争,曾经与她因为一点小事辩论过很久。

    孙志刚死亡后,他的父亲和弟弟从湖北黄冈穷困的家乡赶来,翻出了孙生前遗物让记者看,里面有很多获奖证书。“他是我们家乡出的第一个大学生。”不过,现在孙的家人有点后悔供孙志刚读大学了,“如果没有读过书,不认死理,也许他也就不会死……”

  • 被收容者孙志刚之死(一)

    2008-10-22 11:00:34

    本文发表于2003年

    3月17日:在广州点击查看广州及更多城市天气预报街头被带至黄村街派出所

    3月18日:被派出所送往广州收容遣送中转站

    3月18日:被收容站送往广州收容人员救治站

    3月20日:救治站宣布事主不治

    4月18日:尸检结果表明,事主死前72小时曾遭毒打

    孙志刚,男,今年27岁,刚从大学毕业两年。

    2003年3月17日晚10点,他像往常一样出门去上网。在其后的3天中,他经历了此前不曾去过的3个地方:广州黄村街派出所、广州市收容遣送中转站和广州收容人员救治站。

    这3天,在这3个地方,孙志刚究竟遭遇了什么,他现在已经不能告诉我们了。3月20日,孙志刚死于广州收容人员救治站(广州市脑科医院的江村住院部)。

    他的尸体现在尚未火化,仍然保存在殡仪馆内。

    《南方都市报》记者 陈峰

    孙志刚死了

    先被带至派出所,后被送往收容站,再被送往收容人员救治站,之后不治

    孙志刚来广州才20多天。2001年,他毕业于武汉点击查看武汉及更多城市天气预报科技学院,之后在深圳点击查看深圳及更多城市天气预报一家公司工作,20多天前,他应聘来到广州一家服装公司。

    因为刚来广州,孙志刚还没办理暂住证,当晚他出门时,也没随身携带身份证。

    当晚11点左右,与他同住的成先生(化名)接到了一个手机打来的电话,孙志刚在电话中说,他因为没有暂住证而被带到了黄村街派出所。

    在一份《城市收容“三无”人员询问登记表》中,孙志刚是这样填写的:“我在东圃黄村街上逛街,被治安人员盘问后发现没有办理暂住证,后被带到黄村街派出所。”

    孙志刚在电话中让成先生“带着身份证和钱”去保释他,于是,成先生和另一个同事立刻赶往黄村街派出所,到达时已接近晚12点。

    出于某种现在不为人所知的原因,成先生被警方告知“孙志刚有身份证也不能保释”。在那里,成先生亲眼看到许多人被陆续保了出来,但他先后找了两名警察希望保人,但那两名警察在看到正在被讯问的孙志刚后,都说“这个人不行”,但并没解释原因。

    成先生说,其中一个警察还让他去看有关条例,说他们有权力收容谁。

    成先生很纳闷,于是打电话给广州本地的朋友,他的朋友告诉他,之所以警方不愿保释,可能有两种情况,一是孙志刚“犯了事”,二是“顶了嘴”。

    成先生回忆说,他后来在派出所的一个办公窗口看到了孙志刚,于是偷偷跟过去问他“怎么被抓的,有没有不合作”,孙回答说“没干什么,才出来就被抓了”。成先生说,“他(孙志刚)承认跟警察顶过嘴,但他认为自己说的话不是很严重”。

    警察随后让孙志刚写材料,成先生和孙志刚从此再没见过面。

    第二天,孙的另一个朋友接到孙从收容站里打出的电话,据他回忆,孙在电话中“有些结巴,说话速度很快,感觉他非常恐惧”。于是,他通知孙志刚所在公司的老板去收容站保人。之后,孙的一个同事去了一次,但被告知保人手续不全,在开好各种证明以后,公司老板亲自赶到广州市收容遣送中转站,但收容站那时要下班了,要保人得等到第二天。

    3月19日,孙志刚的朋友打电话询问收容站,这才知道孙志刚已经被送到医院(广州收容人员救治站)去了。在护理记录上,医院接收的时间是18日晚11点30分。

    成先生说,当时他们想去医院见孙志刚,又被医生告知不能见,而且必须是孙志刚亲属才能前来保人。

    20日中午,当孙的朋友再次打电话询问时,得到的回答让他们至今难以相信:孙志刚死了,死因是心脏病。

    护理记录表明,入院时,孙志刚“失眠、心慌、尿频、恶心呕吐,意识清醒,表现安静”,之后住院的时间,孙志刚几乎一直“睡眠”:直到3月20日早上10点,护士查房时发现孙志刚“病情迅速变化,面色苍白、不语不动,呼吸微弱,血压已经测不到”。医生在10点15分采取注射肾上腺素等治疗手段,10分钟后,宣布停止一切治疗。孙志刚走完了他27年的人生路。

    医院让孙志刚的朋友去殡仪馆等着。孙的朋友赶到殡仪馆后又过了两个小时,尸体运到。

    护理记录上,孙的死亡时间是2003年3月20日10点25分。

    孙志刚是被打死的

    尸检结果表明:孙志刚死前几天内曾遭毒打并最终导致死亡

    医院在护理记录中认为,孙是猝死,死因是脑血管意外,心脏病突发。

    在向法医提出尸检委托时,院方的说法仍是“猝死、脑血管意外”。据3月18日的值班医生介绍,孙志刚入院时曾说自己有心脏病史,据此推断孙志刚死于心脏病。但是,这个说法遭到了孙志刚家属和同学的反驳,孙志刚父亲表示,从来不知道儿子有心脏病。

    同样,法医尸检的结果也推翻了院方的诊断。在中山大学中山医学院法医鉴定中心4月18日出具的检验鉴定书中,明确指出:“综合分析,孙志刚符合大面积软组织损伤致创伤性休克死亡”。

    虽然孙的身体表面上看不出致命伤痕,但是在切开腰背部以后,法医发现,孙志刚的皮下组织出现了厚达3·5厘米的出血,其范围更是大到60×50厘米。孙志刚生前是一个身高一米七四、肩宽背阔的小伙子,这么大的出血范围,意味着他整个背部差不多全都是出血区了。

    “翻开肌肉,到处都是一砣一砣的血块”4月3日,中山大学中山医学院法医鉴定中心解剖孙志刚尸体,孙志刚的两个叔叔孙兵武和孙海松在现场目睹了解剖过程。“惨不忍睹!”孙兵武说,“尸体上没穿衣服,所以伤很明显。”

    孙兵武说,他看到孙志刚双肩各有两个直径约1·5厘米的圆形黑印,每个膝盖上,也有五六个这样的黑印,这些黑印就像是“滴到白墙上的黑油漆那样明显”。孙兵武说,他当时听到一名参加尸体解剖的人说“这肯定是火烫的”。

    孙兵武说,他看到在孙志刚的左肋部,有一团拳头大小的红肿,背部的伤甚至把负责尸检的医生“吓了一跳”,“从肩到臀部,全是暗红色,还有很多条长条状伤痕。”医生从背部切下第一刀,随着手术刀划动,一条黑线显现出来,切下第二刀的时候,显现出一砣砣的黑血块。

    法医的检查还证明,死者的其他内脏器官没有出现问题,“未见致死性病理改变”。

    法医的尸检结果表明:孙志刚死亡的原因,就是背部大面积的内伤。

    鉴定书上的“分析说明”还指出,孙的身体表面有多处挫擦伤,背部可以明显看到条形皮下出血,除了腰背部的大面积出血以外,肋间肌肉也可以看到大面积出血。

    “从软组织大面积损伤到死亡,这个过程一般发生在72小时内。”广州市第一人民医院一名外科医生介绍:“软组织损伤导致细胞坏死出血,由于出血发生在体内,所以眼睛看不见,情况严重会导致广泛性血管内融血,这一症状也被称作DIC。DIC是治疗的转折点,一旦发生,患者一般会迅速死亡,极难救治。所以类似的治疗,早期都以止血、抗休克为主,目的是阻止病情进入DIC阶段,没有发生DIC,患者生还希望极大。”

    3月18日晚上11点30分,孙志刚被收容站工作人员送到医院(广州市收容人员救治站)。当天值班医生在体检病历“外科情况”一栏里的记录只有一个字:“无”,“精神检查”一栏里的记录是“未见明显异常,情感适切”,初步印象判断孙志刚患有焦虑症或心脏病。

    对于孙志刚背部大面积暗红色肿胀,双肩和双膝上可疑的黑点以及肋部明显的红肿,病历上没有任何记录。在采访中,当晚的值班医生承认,由于当晚天黑,没有发现孙志刚的外伤,第二天,“由于患者穿着衣服,也没有主动说有外伤”,还是没有发现孙志刚严重的外伤。

    “(护理记录中)所谓的睡眠很可能其实是休克”,广州市第一人民医院的外科医生:“由于内脏出血,血压下降,患者会出现创伤性休克,这是发生DIC症状的前兆之一,应该立即采取抢救措施。”

    但是护理记录上,还只是注明“(患者)本班睡眠”。

    按法医的说法,孙志刚体内的大出血,是被钝物打击的结果,而且不止一次。“一次打击解释不了这么大面积的出血”,一名不愿意透露姓名的法医在看完尸检结果以后说。

    从尸检结果看,孙志刚死前几天内被人殴打并最终导致死亡已是不争的事实。

    更值得注意的是,孙身体表面的伤痕并不多,而皮下组织却有大面积软组织创伤,法医告诉记者,一般情况,在冬季穿着很厚的衣服的情况下,如果被打,就会出现这种情况。

    而3月17日至3月20日的有关气象资料表明,广州市温度在16℃—28℃之间,这样的天气,孙当然不可能“穿得像冬天一样”。

    那3天,孙志刚在黄村街派出所、收容站和医院度过的最后生涯,看来远不像各种表格和记录中写得那么平静。

  • 企业管理的精髓

    2008-10-21 17:27:51

    企业管理的精髓:
          一男赶集卖猪,天黑遇雨,二十头猪未卖成,到一农家借宿。
          少妇说:家里只一人不便。
          男:求你了大妹子,给猪一头。
          女:好吧,但家只有一床。
          男:我也到床上睡,再给猪一头。
          女:同意。
          半夜男与女商量,我到你上面睡,女不肯。
          男:给猪两头。
          女允,要求上去不能动。
          少顷,男忍不住,央求动一下,女不肯。
          男:动一下给猪两头。女同意。
          男动了八次停下,女问为何不动?
          男说猪没了。
          女小声说:要不我给你猪……
          天亮后,男吹着口哨赶30头(含少妇家的10头)猪赶集去了……
          哈佛导师评论:要发现用户潜在需求,前期必须引导,培养用户需求,因此产生的投入是符合发展规律的。
          另一男得知此事,决意如法炮制,遂赶集卖猪,天黑遇雨,二十头猪未卖成,到一农家借宿。
          少妇说:家里只一人不便。
          男:求你了大妹子,给猪一头。
          女:好吧,但家只有一床。
          男:我也到床上睡,再给猪一头。
          女:同意。半夜男商女,我到你上面睡,女不肯。
          男:给猪两头。
          女允,要求上去不能动。
          少顷,男忍不住,央求动一下,女不肯。
          男:动一下给猪两头。
          女同意。男动了七次停下,女问为何不动?
          男说:完事了~~~
          女:……
          天亮后,男低着头赶2头猪赶集去了......
          评论:要结合企业自身规模进行谨慎投资,谨防资金被套。
  • 关系

    2008-10-21 17:26:36

    老总对秘书说:这几天我带你去北京走走.你准备下.
    
    秘书打电话给老公:这几天我要和老总去北京开会,你自己照顾自己.
    
    老公给情人打电话:我老婆这几天要去北京出差,我们也出来玩吧.
    
    情人给辅导功课的小男孩打电话:这几天不用上课,我有事情.
    
    小男孩给爷爷打电话:爷爷,这几天老师有事,不用上课,你陪我玩吧
    
    爷爷给秘书打电话:我这几天要陪孙子玩,不能去北京了.
    
    秘书给老公打电话:这几天老总有急事,我们不去北京开会了.
    
    
    老公给情人打电话:这几天不能出来玩,我老婆不去北京了.
    
    情人给辅导功课的小男孩电话:这几天继续正常上课.
    
    小男孩给爷爷电话:爷爷,这几天还是要上课,我不能陪你玩了.
    
    爷爷给秘书电话:这几天我还是带你去北京走走的.你准备下。
  • Java线程总结(转)

    2008-10-21 16:43:23

    Java线程总结(转)



    在论坛上面常常看到初学者对线程的无可奈何,所以总结出了下面一篇文章,希望对一些正在学习使用java线程的初学者有所帮助。

    首先要理解线程首先需要了解一些基本的东西,我们现在所使用的大多数操作系统都属于多任务,分时操作系统。正是由于这种操作系统的出现才有了多线程这个概念。我们使用的windows,linux就属于此列。什么是分时操作系统呢,通俗一点与就是可以同一时间执行多个程序的操作系统,在自己的电脑上面,你是不是一边听歌,一边聊天还一边看网页呢?但实际上,并不上cpu在同时执行这些程序,cpu只是将时间切割为时间片,然后将时间片分配给这些程序,获得时间片的程序开始执行,不等执行完毕,下个程序又获得时间片开始执行,这样多个程序轮流执行一段时间,由于现在cpu的高速计算能力,给人的感觉就像是多个程序在同时执行一样。
    一般可以在同一时间内执行多个程序的操作系统都有进程的概念.一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间,一组系统资源.在进程概念中,每一个进程的内部数据和状态都是完全独立的.因此可以想像创建并执行一个进程的系统开像是比较大的,所以线程出现了。在java中,程序通过流控制来执行程序流,程序中单个顺序的流控制称为线程,多线程则指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务.多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行.(你可以将前面一句话的程序换成进程,进程是程序的一次执行过程,是系统运行程序的基本单位)

    线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈.所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程也被称为轻负荷进程(light-weight process).一个进程中可以包含多个线程.

    多任务是指在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每个任务对应一个进程,同进程一样,一个线程也有从创建,运行到消亡的过程,称为线程的生命周期.用线程的状态(state)表明线程处在生命周期的哪个阶段.线程有创建,可运行,运行中,阻塞,死亡五中状态.通过线程的控制与调度可使线程在这几种状态间转化每个程序至少自动拥有一个线程,称为主线程.当程序加载到内存时,启动主线程.

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


    线程的状态表示线程正在进行的活动以及在此时间段内所能完成的任务.线程有创建,可运行,运行中,阻塞,死亡五中状态.一个具有生命的线程,总是处于这五种状态之一:
    1.
    创建状态
    使用new运算符创建一个线程后,该线程仅仅是一个空对象,系统没有分配资源,称该线程处于创建状态(new thread)
    2.
    可运行状态
    使用start()方法启动一个线程后,系统为该线程分配了除CPU外的所需资源,使该线程处于可运行状态(Runnable)
    3.
    运行中状态
    Java
    运行系统通过调度选中一个Runnable的线程,使其占有CPU并转为运行中状态(Running).此时,系统真正执行线程的run()方法.
    4.
    阻塞状态
    一个正在运行的线程因某种原因不能继续运行时,进入阻塞状态(Blocked)
    5.
    死亡状态
    线程结束后是死亡状态(Dead)

    同一时刻如果有多个线程处于可运行状态,则他们需要排队等待CPU资源.此时每个线程自动获得一个线程的优先级(priority),优先级的高低反映线程的重要或紧急程度.可运行状态的线程按优先级排队,线程调度依据优先级基础上的"先到先服务"原则.
    线程调度管理器负责线程排队和CPU在线程间的分配,并由线程调度算法进行调度.当线程调度管理器选种某个线程时,该线程获得CPU资源而进入运行状态.

    线程调度是先占式调度,即如果在当前线程执行过程中一个更高优先级的线程进入可运行状态,则这个线程立即被调度执行.先占式调度分为:独占式和分时方式.
    独占方式下,当前执行线程将一直执行下去,直 到执行完毕或由于某种原因主动放弃CPU,CPU被一个更高优先级的线程抢占
    分时方式下,当前运行线程获得一个时间片,时间到时,即使没有执行完也要让出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
    }
    }






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



    new MyThread_1().start()





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



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





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



    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
    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



    线程的优先级分为10级,分别用110的整数代表,默认情况是5。上面的t2.setPriority(Thread.MAX_PRIORITY)等价与t2.setPriority(10
    然后是线程程序本身的设计,比如使用sleep,yield,joinwait等方法(详情请看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方法的时候需要捕捉异常
    {
    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中添加了休眠语句,当线程休眠的时候就会让出cpucpu将会选择执行处于runnable状态中的其他线程,当然也可能出现这种情况,休眠的Thread立即进入了runnable状态,cpu再次执行它。
    [
    线程组概念]
    线程是可以被组织的,java中存在线程组的概念,每个线程都是一个线程组的成员,线程组把多个线程集成为一个对象,通过线程组可以同时对其中的多个线程进行操作,如启动一个线程组的所有线程等.Java的线程组由java.lang包中的Thread——Group类实现.
    ThreadGroup
    类用来管理一组线程,包括:线程的数目,线程间的关系,线程正在执行的操作,以及线程将要启动或终止时间等.线程组还可以包含线程组.Java的应用程序中,最高层的线程组是名位main的线程组,main中还可以加入线程或线程组,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
    另外一个比较多就是关于线程同步方面的,试想这样一种情况,你有一笔存款在银行,你在一家银行为你的账户存款,而你的妻子在另一家银行从这个账户提款,现在你有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("
    余额不足!");
    }
    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++)
    {
    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);
    }
    }
    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]
    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方法后,线程将被挂起,直到被另一线程唤醒(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){}
    }
    }
    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);
    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_2synchronized(lock)改为synchronized(this),那么执行这个程序的时候将会抛出java.lang.IllegalMonitorStateException执行期异常。另外wait and notify方法是Object中的,并不在Thread这个类中。最后你可能注意到了这点:int[] in=new int[0];为什么不是创建new Object而是一个0长度的数组,那是因为在java中创建一个0长度的数组来充当锁更加高效。

    Thread
    作为java中一重要组成部分,当然还有很多地方需要更深刻的认识,上面只是对Thread的一些常识和易错问题做了一个简要的总结,若要真正的掌握java的线程,还需要自己多做总结

  • 关于函数lr_eval_string

    2008-10-21 16:20:24

    在LR中,C的变量和LR的参数是不一样的。
    任何C的变量都不能被LR的函数直接调用。
    应该用lr_eval_string来取值。
    比如{NewParam}(LR中参数化的变量)直接用这个引用是没有问题的。
    但是如果如下:
      Action()
    {
        char a[10];
        strcpy(a,"{NewParam}");
        lr_message(a);
        return 0;
    }
    这就不对了。 
    lr_message(a);就会报错。
    但是写成lr_message(lr_eval_string(a));就可以。
    因为这里的值已经取出来了。

    再看另一个问题:一个网友说:
    Action()
    {
        char a[10];
        strcpy(a,"{NewParam}");
        lr_message(lr_eval_string(a));
            if (lr_eval_string(a)[0] == 11) {
                    lr_message ("a=%d",a);
            }
            return 0;
    }
    中的 if (lr_eval_string(a)[0] == 11)不应该通过语法检查。
    其中{NewParam}是参数化的。内容:11.


    那下面我来用lr_message ("a=d",lr_eval_string(a)[0]);在if前面打出来看看是什么。结果打出来是:49(数字1的ascii码).
    也就是说if (lr_eval_string(a)[0] == 11)是判断1的ascii码是否等于11.显示是不相等的。于是这里的  lr_message ("a=%d",a);就不会执行。


    下面我们用另一段代码来看看:
    char *str2="T";
    char a[10];
    strcpy(a,lr_eval_string("{NewParam}"));
    lr_message ("a=%d",lr_eval_string(a)[0]);
    lr_message(lr_eval_string(a));
           
    if (lr_eval_string(a)[0]== *str2) {
                    lr_message ("a=%s",a);
      lr_message ("执行这句!");
            }
    结果如下:
    Starting action Action.
    a=84
    T
    a=T
    执行这句!
    Ending action Action.
    这里我的参数是一个大写的“T”。
    我们看到lr_eval_string(a)[0]取到的是大写字母“T”的ascii码。

  • SQA简介

    2008-10-21 15:05:54

                                                          SQA 

          软件质量保证(SQA)是建立一套有计划,有系统的方法,来向管理层保证拟定出的标准、步骤、实践和方法能够正确地被所有项目所采用。  

          软件质量保证的目的是使软件过程对于管理人员来说是可见的。它通过对软件产品和活动进行评审和审计来验证软件是合乎标准的。软件质量保证组在项目开始时就一起参与建立计划、标准和过程。这些将使软件项目满足机构方针的要求。

    一、基本目标 
          目标 1: 软件质量保证工作是有计划进行的。
          目标 2: 客观地验证软件项目产品和工作是否遵循恰当的标准、步骤和需求。
          目标 3: 将软件质量保证工作及结果通知给相关组别和个人。
          目标 4: 高级管理层接触到在项目内部不能解决的不符合类问题。
     
    二、QA的由来
         我们知道,国外很多的大公司,QA的职责就是测试(主要是系统测试),比如IBM、CA、PeopleSoft等。其实在最初,几乎所有的公司都是这样的。后来,由于缺乏有效的项目计划和项目管理,留给系统测试的时间很少(注:我以前做的一个项目,项目经理就明确告诉我系统测试就1天,没得商量)。另外,需求变化太快,没有完整的需求文档,测试人员就只能根据自己的想象来测试。这样一来,测试就很难保障产品的质量,事先预防的QA职能就应运而生。
    事先预防其实是借鉴了TQM的思想,而且也符合软件工程“缺陷越早发现越早修改越经济”的原则。这些思想的渊源还可以追溯到中国古代的典故中,比如曲突徙薪、扁鹊论医术等。特别是扁鹊论医术这个典故,我偶然在国外的一篇文章中看到了(后来在林锐的文章中也看到了),常感叹我们国人连祖先的思想文化遗产都丢的差不多了。

    三、QA的现在
         目前,实施CMM的企业越来越多了。CMM模型就要求建立QA角色。这里的QA类似于过程警察,主要职责是,检查开发和管理活动是否与已定的过程策略、标准和流程一致,检查工作产品是否遵循模板规定的内容和格式。在这些企业中,一般还要求QA独立于项目组,以保障评价的客观性。从国内来看,多数的QA没有技术背景,检查出的偏差多为鸡毛蒜皮,再加上自己没有令人信服的背景,领导也不支持,当然做起来就很困难了。
          缺乏信任和支持只是一个方面,QA工作本身就很具挑战性。它要求QA具有软件工程的知识、软件开发的知识、行业背景的知识、数理统计的知识、项目管理的知识、质量管理的知识等等。
         我们常常遇到这样的问题,改进到一定程度就很难突破,感觉心有余而力不足了,就开始郁闷了。后来通过学习、培训、交流,思想和技能得到升华,又发现了木桶中最短的那块,然后又开始改进,然后又遇到了玻璃天花板,然后……就这样处于郁闷的循环中。
          假使我们掌握了所有的知识,能突破所有的玻璃天花板,那是不是QA就可以一帆风顺了。答案是否定的。QA角色定义本身就有很大的局限性。QA充当的是过程警察的角色,无论是否有意义,都专横地强制过程的执行,容易在项目组中造成敌对的关系,受到排挤,而且这种警察的姿态也破坏了团队精神。如此一来,QA工作还需要的是人际关系技能,就如我以前写的《质量平衡》和《QA应该独立于项目组吗?》一样,艺术化地处理这种关系。
      

    四、QA的未来
          从某种程度上说,独立的QA审查机制是瀑布模型的产物。随着现代软件开发技术的演变,螺旋模型和迭代模型的兴起,QA机制正在悄然发生变化。这种变化就是从独立专职的QA向贯穿过程的兼职QA演变。在CMMI模型中,这种兼职的QA也是被允许的。为什么会发生这种改变呢?无论是XP、RUP还是其它先进的方法论,都是先产生架构,然后再增量开发,直到完成。这种模式中,需求和设计缺陷在各个迭代周期被所尽早发现和修复,质量也内建于架构和过程中,项目的成本和进度也得到保障。
    到那时,是不是独立的QA就不复存在了呢?有些成熟度较低的企业还是需要的,主要是保证过程执行的有效性和评价的客观性。
      

    五、SQA的理论探索

         1、过程的认识
          我们都知道一个项目的主要内容是:成本、进度、质量;良好的项目管理就是综合三方面的因素,平衡三方面的目标,最终依照目标完成任务。项目的这三个方面是相互制约和影响的,有时对这三方面的平衡策略甚至成为一个企业级的要求,决定了企业的行为,我们知道 IBM的软件是以质量为最重要目标的,而微软的“足够好的软件”策略更是耳熟能详,这些质量目标其实立足于企业的战略目标。所以用于进行质量保证的SQA 工作也应当立足于企业的战略目标,从这个角度思考SQA,形成对SQA的理论认识。  
          软件界已经达成共识的:影响软件项目进度、成本、质量的因素主要是 “人、过程、技术”。首先要明确的是这三个因素中,人是第一位的。
          现在许多实施 CMM的人员沉溺于CMM的理论过于强调“过程”,这是很危险的倾向。这个思想倾向在国外受到了猛烈抨击,从某种意义上各种敏捷过程方法的提出就是对强调过程的一种反思。 “XP”中的一个思想“人比过程更重要” 是值得我们思考的。我个人的意见在进行过程改进中坚持“以人为本”,强调过程和人的和谐。

          根据现代软件工程对众多失败项目的调查,发现管理是项目失败的主要原因。这个事实的重要性在于说明了 “要保证项目不失败,我们应当更加关注管理”,注意这个事实没有说明另外一个问题“良好的管理可以保证项目的成功”。现在很多人基于一种粗糙的逻辑,从一个事实反推到的这个结论,在逻辑上是错误的,这种错误形成了更加错误的做法,这点在SQA的理解上是体现较深。
          如果我们考证一下历史的沿革,应当更加容易理解 CMM的本质。CMM首先是作为一个“评估标准”出现的,主要评估的是美国国防部供应商保证质量的能力。CMM关注的软件生产有如下特点:
          (1)质量重要
          (2)规模较大

          这是 CMM产生的原因。它引入了“全面质量管理”的思想,尤其侧重了“全面质量管理”中的“过程方法”,并且引入了“统计过程控制”的方法。可以说这两个思想是CMM背后的基础。

          上面这些内容形成了我对软件过程地位、价值的基本理解;在这个基础上我们可以引申讨论 SQA。
      

          2、生产线的隐喻
          如果将一个软件生产类比于一个工厂的生产。那么生产线就是过程,产品按照生产线的规定过程进行生产。 SQA的职责就是保证过程的执行,也就是保证生产线的正常执行。
          抽象出管理体系模型的如下,这个模型说明了一个过程体系至少应当包含 “决策、执行、反馈”三个重要方面。

         QA的职责就是确保过程的有效执行,监督项目按照过程进行项目活动;它不负责监管产品的质量,不负责向管理层提供项目的情况,不负责代表管理层进行管理,只是代表管理层来保证过程的执行。
      

      

          3、SQA和其他工作的组合 
         在很多企业中,将 SQA的工作和QC、SEPG、组织级的项目管理者的工作混合在一起了,有时甚至更加注重其他方面的工作而没有做好SQA的本职工作。

         根据 hjhza 的意见“中国现在基本有三种QA(按照工作重点不同来分):一是过程改进型,一是配置管理型,一是测试型”。我个人认为是因为SQA工作和其他不同工作组合在一起形成的。

        下面根据本人经验对它们之间的关系进行一个说明。

          4、QA和QC

          两者基本职责

          QC:检验产品的质量,保证产品符合客户的需求;是产品质量检查者;
          QA:审计过程的质量,保证过程被正确执行;是过程质量审计者;

        注意区别检查和审计的不同 

          检查:就是我们常说的找茬,是挑毛病的;

          审计:来确认项目按照要求进行的证据;仔细看看CMM中各个KPA中SQA的检查采用的术语大量用到了“证实”,审计的内容主要是过程的;对照CMM看一下项目经理和高级管理者的审查内容,他们更加关注具体内容。

          对照上面的管理体系模型,QC进行质量控制,向管理层反馈质量信息;QA则确保QC按照过程进行质量控制活动,按照过程将检查结果向管理层汇报。这就是QA和QC工作的关系。

          在这样的分工原则下, QA只要检查项目按照过程进行了某项活动没有,产出了某个产品没有;而QC来检查产品是否符合质量要求。

          如果企业原来具有 QC人员并且QA人员配备不足,可以先确定由QC兼任QA工作。但是只能是暂时的,独立的QA人员应当具备,因为QC工作也是要遵循过程要求的,也是要被审计过程的,这种混合情况,难以保证QC工作的过程质量。

          5、QA和SEPG

          两者基本职责

          SEPG:制定过程,实施过程改进;
          QA: 确保过程被正确执行

         SEPG应当提供过程上的指导,帮助项目组制定项目过程,帮助项目组进行策划;从而帮助项目组有效的工作,有效的执行过程。如果项目和QA对过程的理解发生争持,SEPG作为最终仲裁者。为了进行有效过程改进,SEPG必须分析项目的数据。

         QA本也要进行过程规范,那么所有QA中最有经验、最有能力的QA可以参加SEPG,但是要注意这两者的区别。

          如果企业的 SEPG人员具有较为深厚的开发背景,可以兼任SQA工作,这样利于过程的不断改进;但是由于立法、执法集于一身也容易造成SQA过于强势,影响项目的独立性。

         管理过程比较成熟的企业,因为企业的文化和管理机制已经健全, SQA职责范围的工作较少,往往只是针对具体项目制定明确重点的SQA计划,这样SQA的审计工作会大大减少,从而可以同时审计较多项目。

         另一方面,由于分工的细致化,管理体系的复杂化,往往需要专职的 SEPG人员,这些人员要求了解企业的所有管理过程和运作情况,在这个基础上才能统筹全局的进行过程改进,这时了解全局的SQA人员就是专职SEPG的主要人选;这些SQA人员将逐渐的转化为SEPG人员,并且更加了解管理知识,而SQA工作渐渐成为他们的兼职工作。 

          这种情况在许多 CMM5企业比较多见,往往有时看不见SQA人员在项目组出现或者很少出现,这种SEPG和SQA的融合特别有利于组织的过程改进工作。SEPG确定过程改进内容,SQA计划重点反映这些改进内容,从保证有效的改进,特别有利于达到CMM5的要求。从这个角度,国外的SQA人员为什么高薪就不难理解了,也决定了当前中国SQA人员比较被轻视的原因;因为管理过程还不完善,我们的SQA人员还没有产生这么大的价值嘛!

         6、QA和组织级的监督管理

         有的企业为了更好的监督管理项目,建立了一个角色,我取名为 “组织级的监督管理者”,他们的职责是对所有项目进行统一的跟踪、监督、适当的管理,来保证管理层对所有项目的可视性、可管理性。 

         为了有效管理项目, “组织级的监督管理者”必须分析项目的数据。 
          他们的职责对照上图的模型,就是执行 “反馈”职能。
     
          QA本身不进行反馈工作,最多对过程执行情况的信息进行反馈。

         SQA职责最好不要和“组织级的项目管理者”的职责混合在一起,否则容易出现SAQ困境:一方面SQA不能准确定位自己的工作,另一方面过程执行者对SQA人员抱有较大戒心。 
          如果建立了较好的管理过程,那么就会增强项目的可视性,从而保证企业对所有项目的较好管理;而 QA来确保这个管理过程的运行。


    五、SQA的工作内容和工作方法

          1、 计划

         针对具体项目制定 SQA计划,确保项目组正确执行过程。制定SQA计划应当注意如下几点: 
          有重点:依据企业目标以及项目情况确定审计的重点
          明确审计内容:明确审计哪些活动,那些产品
          明确审计方式:确定怎样进行审计
          明确审计结果报告的规则:审计的结果报告给谁

        2、审计/证实 
         依据 SQA计划进行SQA审计工作,按照规则发布审计结果报告。 
        注意审计一定要有项目组人员陪同,不能搞突然袭击。双方要开诚布公,坦诚相对。 
        审计的内容:是否按照过程要求执行了相应活动,是否按照过程要求产生了相应产品。

         3、问题跟踪 

        对审计中发现的问题,要求项目组改进,并跟进直到解决。


    六、SQA的素质 
         过程为中心:应当站在过程的角度来考虑问题,只要保证了过程, QA就尽到了责任。

         服务精神:为项目组服务,帮助项目组确保正确执行过程 

          了解过程:深刻了解企业的工程,并具有一定的过程管理理论知识

          了解开发:对开发工作的基本情况了解,能够理解项目的活动

         沟通技巧:善于沟通,能够营造良好的气氛,避免审计活动成为一种找茬活动。

    七、SQA活动

         软件质量保证(SQA)是一种应用于整个软件过程的活动,它包含:
          1、一种质量管理方法
          2、有效的软件工程技术(方法和工具)
          3、在整个软件过程中采用的正式技术评审
          4、一种多层次的测试策略
          5、对软件文档及其修改的控制
          6、保证软件遵从软件开发标准
          7、度量和报告机制

       SQA与两种不同的参与者相关 —— 做技术工作的软件工程师和负责质量保证的计划、监督、记录、分析及报告工作的SQA小组 。

       软件工程师通过采用可靠的技术方法和措施,进行正式的技术评审,执行计划周密的软件测试来考虑质量问题,并完成软件质量保证和质量控制活动。

      SQA小组的职责是辅助软件工程小组得到高质量的最终产品。SQA小组完成:

    (1)为项目准备SQA计划。该计划在制定项目规定项目计划时确定,由所有感兴趣的相关部门评审。
    ·需要进行的审计和评审;
    ·项目可采用的标准;
    ·错误报告和跟踪的规程;
    ·由SQA小组产生的文档;
    ·向软件项目组提供的反馈数量。
    (2)参与开发项目的软件过程描述。评审过程描述以保证该过程与组织政策,内部软件标准,外界标准以及项目计划的其他部分相符。
    (3)评审各项软件工程活动,对其是否符合定义好的软件过程进行核实。记录、跟踪与过程的偏差。
    (4)审计指定的软件工作产品,对其是否符合事先定义好的需求进行核实。对产品进行评审,识别、记录和跟踪出现的偏差;对是否已经改正进行核实;定期将工作结果向项目管理者报告。
    (5)确保软件工作及产品中的偏差已记录在案,并根据预定的规程进行处理。
    (6)记录所有不符合的部分并报告给高级领导者。

    八、正式技术评审(FTR)

      正式技术评审是一种由软件工程师和其他人进行的软件质量保障活动。

    1. 目标:
    (1) 发现功能、逻辑或实现的错误
    (2) 证实经过评审的软件的确满足需求
    (3) 保证软件的表示符合预定义的标准
    (4) 得到一种一致的方式开发的软件
    (5) 使项目更易管理

    2、评审会议
    3-5人参加,不超过2小时,由评审主席、评审者和生产者参加,必须做出下列决定中的一个 :
    (1)工作产品可不可以不经修改而被接受;
    (2)由于严重错误而否决工作产品;
    (3)暂时接受工作产品。

    3、评审总结报告、回答
    评审什么?由谁评审?结论是什么?
    评审总结报告是项目历史记录的一部分,标识产品中存在问题的区域,作为行政条目检查表以指导生产者进行改正。

    4、评审指导原则
    (1)评审产品,而不是评审生产者。注意客气地指出错误,气氛轻松。
    (2)不要离题,限制争论。有异议的问题不要争论但要记录在案。
    (3)对各个问题都发表见解。问题解决应该放到评审会议之后进行。
    (4)为每个要评审的工作产品建立一个检查表。应为分析、设计、编码、测试文档都建立检查表。
    (5)分配资源和时间。应该将评审作为软件工程任务加以调度。
    (6)评审以前所做的评审

    九、统计软件质量保证

    1、对所有错误进行分类统计
    IES    规约不完整或规格说明错
    MCC  未理解用户意图
    IDS    故意偏离规格说明
    VPS    违背编程标准
    EDR    数据表示有错
    ICI     构件接口不一致
    EDL    设计逻辑有错
    IET     测试不完全或有错
    IID     不准确或不完整的文档
    PLT     设计的程序设计语言翻译错
    HCI     不清晰或不一致的人机界面
    MIS     杂项错误
    按严重,一般和微小级别统计各类错误的次数所占百分比,以及所有错误的数量及百分比。例如,建立一张类似如下的表格。
     然后考虑“重要少数”的错误指标,提出改进意见。

    2、根据软件过程中的每个步骤计算错误指标。

    Ei = 第i发现的错误总数
    Si = 严重错误数
    Mi = 一般错误数
    Ti = 微小错误数
    PS = 第i步的产品规模( LOC,设计陈述,文档页数)
    Ws,Wm,Wt分别是严重,一般,微小错误的加权因子, 推荐取值,Ws=10,Wm=3,Wt=1
    软件工程 在过程的每一步中,计算各阶段的阶段指标
    PIi = Ws(Si / Ei)+Wm(Mi / Ei)+Wt(Ti / Ei)
    错误指标
    Ei= ∑(i×PIi)/ PS
      =(PI1 + 2PI2 + 3PI3 + … + i*PIi)/ PS
    错误指标与上面表格中收集的信息相结合可以得出软件质量整体改进指标。七、质量保证与检验
    确保每个开发过程的质量,防止把软件差错传播到下一个过程,因此,检验的目的有两个:
    1.切实搞好开发阶段的管理,检查各开发阶段的质量保证。
    2.预先防止软件差错给用户造成损失。

    检验的类型有:
    1.供货检验:对委托外单位承担开发作业,而后买进或转让的构成软件产品的部件,规格说明,半成品或产品的检查。
    2.中间检验 / 阶段评审
    目的是为了判断是否可进入下阶段进行后续开发,避免将差错传播到后续工作中。
    3.验收检验:
    确认产品是否已达到可以进行产品检验的质量要求。
    4.产品检验:
    判定向用户提供的软件产品是否达到令人满意的程度。


    十、检验项目内容

    1.需求分析
    需求分析→功能设计→实施计划
    检查:开发目的;目标值;开发量;所需资源;各阶段的产品作业内容及开发体制的合理性。
    2.设计
    结构设计→数据设计→过程设计
    检查:产品的计划量与实际量;评审量;差错数;评审方法,出错导因及处理情况,阶段结束的判断标准。
    3.实现
    程序编制→单元测试→集成测试→确认测试.检查内容除上述外,加测试环境及测试用例设计方法。
    4.验收
    说明书检查;程序检查。


    1.3质量保证实施

          软件质量评价标准。
    1.质量需求准则:着眼点是是否满足用户的要求
    2.质量设计准则:开发者在设计实现时是否按软件需求保证了质量
    3.质量度量准则:为质量度量规定了一些检查项目:
       精密度量:根据质量度量准则进行详细度量
       全面度量
       简易度量 


          五个实施步骤
    1.Target:以用户需求和开发任务为依据,对质量需求准则,质量设计准则的质量特性设定质量目标进行评价。
    2.Plan:设定适合于待开发软件的评测检查项目,一般设定20—30个。
    3.DO:在开发标准和质量评价准则的指导下,制作高质量的规格说明书和程序。
    4.Check:以Plan阶段设定的质量评价准则进行评价,算出得分,以质量图的形成表示出来,比较评价结果的质量得分和质量目标看其是否合格。
    5.Action:对评价发现的问题进行改进活动,重复Plan到Action的过程直到开发项目完成。


    1.4  软件可靠性

          可靠性统计定义:
    在给定的环境和给定的时间间隔内,按设计要求成功运行程序的概率。
    二、软件可靠性的主要指标
    MTBF —— 平均故障间隔时间
    MTTF —— 平均故障时间
    MTTR —— 平均修复时间
    MTBF = MTTF + MTTR
    软件可用性是指在某个给定时间点程序能够按照需求执行的概率。
    可用性 = MTTF /(MTTF+MTTR)×100%

    1.5   ISO9000 质量标准  

    ISO9000标准被很多国家采用,包括欧盟的所有成员,加拿大、墨西哥、美国、澳大利亚、新西兰和太平洋区域。为了注册成为ISO9000中包含的质量保证系统模型中的一种,一个公司的质量系统和操作应该由第三方审计者仔细检查,查看其标准的符合性以及操作的有效性。成功注册之后,这一公司将收到由审计者所代表的注册实体颁发的证书。此后,每半年进行一次检查性审计。
    ISO9001是应用于软件工程质量保证标准。这一标准中包含了高效的质量保证系统必须体现的20条需求。因为ISO9001标准,适用于所有的工程行业,因此,为帮助解释该标准在软件过程中的使用而专门开发了一个ISO指南的子集ISO9000—3。
    ISO9001描述的需求涉及到管理责任,质量系统,合约评审,设计控制,文档和数据控制,产品标识和跟踪,过程和控制,审查和测试,纠正和预防性动作,质量控制记录,内部质量审计,培训,服务以及统计技术的主题.

  • 魔兽三秘籍,哈哈

    2008-08-13 09:35:29

    在游戏中按下 Enter键叫出对话框后输入密技
    如果输入正确会出现 Cheat enabled 字样
    greedisgood =黄金木材各加500单位
    KeyserSoze =加黄金
    LeafItToMe =加木材
    PointBreak =加人口上限
    whosyourdaddy =无敌且拥有一击必杀
    iseedeadpeople =显示全部地图
    allyourbasearebelongtous =立即获胜
    somebodysetupusthebomb =立即战败
    ItVexesMe =不会被判定获胜
    StrengthAndHonor =不会被判定战败
    thereisnospoon =法力无限
    WhoIsJohnGalt =研发加速
    WarpTen =快速建筑
    SharpAndShiny =建筑物升级
    Synergy =科技全开
    RiseAndShine =黎明
    LightsOut =黄昏
    DaylightSavings =调整时间
    Motherland =跳关 (如 human 04)
    IocainePowder =fastdeath
    TheDudeAbides =cooldown

  • HP总裁孙振耀退休时的一封信-人生

    2008-07-16 09:39:36

    我有个有趣的观察,外企公司多的是25-35岁的白领,40岁以上的员工很少,二三十岁的外企员工是意气风发的,但外企公司40岁附近的经理人是很尴尬 的。我见过的40岁附近的外企经理人大多在一直跳槽,最后大多跳到民企,比方说,唐骏外企员工的成功很大程度上是公司的成功,并非个人的成功,西门子的 确比国美大,但并不代表西门子中国经理比国美的老板强,甚至可以说差得很远。而进外企的人往往并不能很早理解这一点,把自己的成功90%归功于自己的能 力,实际上,外企公司随便换个中国区总经理并不会给业绩带来什么了不起的影响。好了问题来了,当这些经理人40多岁了,他们的薪资要求变得很高,而他们的 才能其实又不是那么出众,作为外企公司的老板,你会怎么选择?有的是只要不高薪水的,要出位的精明强干精力冲沛的年轻人,有的是,为什么还要用你?

      从上面这个例子,其实可以看到我们的工作轨迹,二三十岁的时候,生活的压力还比较小,身体还比较好,上面的父母身体还好,下面又没有孩子,不用还房 贷,也没有孩子要上大学,当个外企小白领还是很光鲜的,挣得不多也够花了但是人终归要结婚生子,终归会老,到了40岁,父母老了,要看病要吃药,要有人 看护,自己要还房贷,要过基本体面的生活,要养小孩……那个时候需要挣多少钱才够花才重要。所以,看待工作,眼光要放远一点,一时的谁高谁低并不能说明什 么

    从这个角度上来说,我不太赞成过于关注第一份工作的薪水,更没有必要攀比第一份工作的薪水,这在刚刚出校园的学生中间是很常见的正常人大概要工作 35年,这好比是一场马拉松比赛,和真正的马拉松比赛不同的是,这次比赛没有职业选手,每个人都只有一次机会。要知到,有很多人甚至坚持不到终点,大多数 人最后是走到终点的,只有少数人是跑过终点的因此在刚开始的时候,去抢领先的位置并没有太大的意义。刚进社会的时候如果进500强公司,大概能拿到3k -6k/月的工资,有些特别技术的人才可能可以到8k/月,可问题是,5年以后拿多少?估计5k-10k了不起了。起点虽然高,但增幅有限,而且,后面的 年轻人追赶的压力越来越大

    我前两天问我的一个销售,你会的这些东西一个新人2年就都学会了,但新人所要求的薪水却只是你的一半,到时候,你怎么办?

      职业生涯就像一场体育比赛,有初赛、复赛、决赛。初赛的时候大家都刚刚进社会,大多数都是实力一般的人,这时候努力一点认真一点很快就能让人脱颖而 出,于是有的人二十多岁做了经理,有的人迟些也终于赢得了初赛,三十多岁成了经理。然后是复赛,能参加复赛的都是赢得初赛的,每个人都有些能耐,在聪明才 智上都不成问题,这个时候再想要胜出就不那么容易了,单靠一点点努力和认真还不够,要有很强的坚忍精神,要懂得靠团队的力量,要懂得收服人心,要有长远的 眼光……

    看上去赢得复赛并不容易,但,还不是那么难。因为这个世界的规律就是给人一点成功的同时让人骄傲自满,刚刚赢得初赛的人往往不知道自己赢得的仅仅是初 赛,有了一点小小的成绩大多数人都会骄傲自满起来,认为自己已经懂得了全部,不需要再努力再学习了,他们会认为之所以不能再进一步已经不是自己的原因了。 虽然他们仍然不好对付,但是他们没有耐性,没有容人的度量,更没有清晰长远的目光。就像一只愤怒的斗牛,虽然猛烈,最终是会败的,而赢得复赛的人则象斗牛 士一样,不急不躁,跟随着自己的节拍,慢慢耗尽对手的耐心和体力。赢得了复赛以后,大约已经是一位很了不起的职业经理人了,当上了中小公司的总经理,大公 司的副总经理,主管着每年几千万乃至几亿的生意

    最终的决赛来了,说实话我自己都还没有赢得决赛,因此对于决赛的决胜因素也只能凭自己的猜测而已,这个时候的输赢或许就像武侠小说里写得那样,大家都 是高手,只能等待对方犯错了,要想轻易击败对手是不可能的,除了使上浑身解数,还需要一点运气和时间。世界的规律依然发挥着作用,赢得复赛的人已经不只是 骄傲自满了,他们往往刚愎自用,听不进去别人的话,有些人的脾气变得暴躁,心情变得浮躁,身体变得糟糕,他们最大的敌人就是他们自己,在决赛中要做的只是 不被自己击败,等着别人被自己击败。这和体育比赛是一样的,最后高手之间的比赛,就看谁失误少谁就赢得了决赛


    根源


    你工作快乐么?你的工作好么?
    有没有觉得干了一段时间以后工作很不开心?有没有觉得自己入错了行?有没有觉得自己没有得到应有的待遇?有没有觉得工作像一团乱麻每天上班都是一种痛 苦?有没有很想换个工作?有没有觉得其实现在的公司并没有当初想象得那么好?有没有觉得这份工作是当初因为生存压力而找的,实在不适合自己?你从工作中得 到你想要得到的了么?你每天开心么?

      天涯上愤怒的人很多,你有没有想过,你为什么不快乐?你为什么愤怒?
    其实,你不快乐的根源,是因为你不知道要什么!你不知道要什么,所以你不知道去追求什么,你不知道追求什么,所以你什么也得不到。


    我总觉得,职业生涯首先要关注的是自己,自己想要什么?大多数人大概没想过这个问题,唯一的想法只是——我想要一份工作,我想要一份不错的薪水,我知 道所有人对于薪水的渴望,可是,你想每隔几年重来一次找工作的过程么?你想每年都在这种对于工作和薪水的焦急不安中度过么?不想的话,就好好想清楚。饮鸩 止渴,不能因为口渴就拼命喝毒药。越是焦急,越是觉得自己需要一份工作,越饥不择食,越想不清楚,越容易失败,你的经历越来越差,下一份工作的人看着你的 简历就皱眉头。于是你越喝越渴,越渴越喝,陷入恶性循环。最终只能哀叹世事不公或者生不逢时,只能到天涯上来发泄一把,在失败者的共鸣当中寻求一点心理平 衡罢了。大多数人都有生存压力,我也是,有生存压力就会有很多焦虑,积极的人会从焦虑中得到动力,而消极的人则会因为焦虑而迷失方向。所有人都必须在压力 下做出选择,这就是世道,你喜欢也罢不喜欢也罢。

      一般我们处理的事情分为重要的事情和紧急的事情,如果不做重要的事情就会常常去做紧急的事情。比如锻炼身体保持健康是重要的事情,而看病则是紧急的事 情。如果不锻炼身体保持健康,就会常常为了病痛烦恼。又比如防火是重要的事情,而救火是紧急的事情,如果不注意防火,就要常常救火。找工作也是如此,想好 自己究竟要什么是重要的事情,找工作是紧急的事情,如果不想好,就会常常要找工作。往往紧急的事情给人的压力比较大,迫使人们去赶紧做,相对来说重要的事 情反而没有那么大的压力,大多数人做事情都是以压力为导向的,压力之下,总觉得非要先做紧急的事情,结果就是永远到处救火,永远没有停歇的时候。(很多人 的工作也像是救火队一样忙碌痛苦,也是因为工作中没有做好重要的事情。)那些说自己活在水深火热为了生存顾不上那么多的朋友,今天找工作困难是当初你们没 有做重要的事情,是结果不是原因。如果今天你们还是因为急于要找一份工作而不去思考,那么或许将来要继续承受痛苦找工作的结果。

      我始终觉得我要说的话题,沉重了点,需要很多思考,远比唐笑打武警的话题来的枯燥乏味,但是,天下没有轻松的成功,成功,要付代价请先忘记一切的生存压力,想想这辈子你最想要的是什么?所以,最要紧的事情,先想好自己想要什么。


    什么是好工作

      当初微软有个唐骏,很多大学里的年轻人觉得这才是他们向往的职业生涯,我在清华bbs里发的帖子被这些学子们所不屑,那个时候学生们只想出国或者去外 企,不过如今看来,我还是对的,唐骏去了盛大,陈天桥创立的盛大,一家民营公司。一个高学历的海归在500强的公司里拿高薪水,这大约是很多年轻人的梦 想,问题是,每年毕业的大学生都在做这个梦,好的职位却只有500个

      人都是要面子的,也是喜欢攀比的,即使在工作上也喜欢攀比,不管那是不是自己想要的。大家认为外企公司很好,可是好在哪里呢?好吧,他们在比较好的写 字楼,这是你想要的么?他们出差住比较好的酒店,这是你想要的么?别人会羡慕一份外企公司的工作,这是你想要的么?那一切都是给别人看的,你干吗要活得那 么辛苦给别人看?另一方面,他们薪水福利一般,并没有特别了不起,他们的晋升机会比较少,很难做到很高阶的主管,他们虽然厌恶常常加班,却不敢不加班,因 为“你不干有得是人干”,大部分情况下会找个台湾人香港人新加坡人来管你,而这些人又往往有些莫名其妙的优越感。你想清楚了么?500强一定好么?找工作 究竟是考虑你想要什么,还是考虑别人想看什么?

      我的大学同学们大多数都到美国了,甚至毕业这么多年了,还有人最近到国外去了。出国真的有那么好么?我的大学同学们,大多数还是在博士、博士后、访问 学者地挣扎着,至今只有一个正经在一个美国大学里拿到个正式的教职。国内的教授很难当么?我有几个表亲也去了国外了,他们的父母独自在国内,没有人照顾, 有好几次人在家里昏倒都没人知道,出国,真的这么光彩么?就像有人说的“很多事情就像看A片,看的人觉得很爽,做的人未必。”


    人总想找到那个最好的,可是,什么是最好的?你觉得是最好的那个,是因为你的确了解,还是因为别人说他是最好的?即使他对于别人是最好的,对于你也一定是最好的么?
    对于自己想要什么,自己要最清楚,别人的意见并不是那么重要。很多人总是常常被别人的意见所影响,亲戚的意见,朋友的意见,同事的意见……问题是,你 究竟是要过谁的一生?人的一生不是父母一生的续集,也不是儿女一生的前传,更不是朋友一生的外篇,只有你自己对自己的一生负责,别人无法也负不起这个责 任。自己做的决定,至少到最后,自己没什么可后悔。对于大多数正常智力的人来说,所做的决定没有大的对错,无论怎么样的选择,都是可以尝试的。比如你没有 考自己上的那个学校,没有入现在这个行业,这辈子就过不下去了?就会很失败?不见得。

      我想,好工作,应该是适合你的工作,具体点说,应该是能给你带来你想要的东西的工作,你或许应该以此来衡量你的工作究竟好不好,而不是拿公司的大小, 规模,外企还是国企,是不是有名,是不是上市公司来衡量。小公司,未必不是好公司,赚钱多的工作,也未必是好工作。你还是要先弄清楚你想要什么,如果你不 清楚你想要什么,你就永远也不会找到好工作,因为你永远只看到你得不到的东西,你得到的,都是你不想要的。
    可能,最好的,已经在你的身边,只是,你还没有学会珍惜。人们总是盯着得不到的东西,而忽视了那些已经得到的东西。


    普通人

      我发现中国人的励志和国外的励志存在非常大的不同,中国的励志比较鼓励人立下大志愿,卧薪尝胆,有朝一日成富成贵。而国外的励志比较鼓励人勇敢面对现 实生活,面对普通人的困境,虽然结果也是成富成贵,但起点不一样,相对来说,我觉得后者在操作上更现实,而前者则需要用999个失败者来堆砌一个成功者的 故事。

    我们都是普通人,普通人的意思就是,概率这件事是很准的。因此,我们不会买彩票中500万,我们不会成为比尔盖茨或者李嘉诚,我们不会坐飞机掉下来,我们当中很少的人会创业成功,我们之中有30%的人会离婚,我们之中大部分人会活过65岁……

    所以请你在想自己要什么的时候,要得“现实”一点,你说我想要做李嘉诚,抱歉,我帮不上你。成为比尔盖茨或者李嘉诚这种人,是靠命的,看我写的这篇文章绝对不会让你成为他们,即使你成为了他们,也绝对不是我这篇文章的功劳。“王侯将相宁有种乎”,但真正当皇帝的只有一个人,王侯将相,人也不多。目标定得高些对于喜欢挑战的人来说有好处,但对于大多数普通人来说,反而比较容易灰心沮丧,很容易就放弃了。

    回过头来说,李嘉诚比你有钱大致50万倍,他比你更快乐么?或许。有没有比你快乐50万倍,一定没有。他比你最多也就快乐一两倍,甚至有可能还不如你 快乐。寻找自己想要的东西不是和别人比赛,比谁要得更多更高,比谁的目标更远大。虽然成为李嘉诚这个目标很宏大,但你并不见得会从这个目标以及追求目标的 过程当中获得快乐,而且基本上你也做不到。你必须听听你内心的声音,寻找真正能够使你获得快乐的东西,那才是你想要的东西。

    你想要的东西,或者我们把它称之为目标,目标其实并没有高低之分,你不需要因为自己的目标没有别人远大而不好意思,达到自己的目标其实就是成功,成功 有大有小,快乐却是一样的。我们追逐成功,其实追逐的是成功带来的快乐,而非成功本身。职业生涯的道路上,我们常常会被攀比的心态蒙住眼睛,忘记了追求的 究竟是什么,忘记了是什么能使我们更快乐。

    社会上一夜暴富的新闻很多,这些消息,总会在我们的心里面掀起很多涟漪,涟漪多了就变成惊涛骇浪,心里的惊涛骇浪除了打翻承载你目标的小船,并不会使 得你也一夜暴富。“只见贼吃肉,不见贼挨揍。”我们这些普通人既没有当贼的勇气,又缺乏当贼的狠辣绝决,虽然羡慕吃肉,却更害怕挨揍,偶尔看到几个没挨揍 的贼就按奈不住,或者心思活动,或者大感不公,真要叫去做贼,却也不敢

    我还是过普通人的日子,要普通人的快乐,至少,晚上睡得着觉。


    跳槽与积累

      首先要说明,工作是一件需要理智的事情,所以不要在工作上耍个性,天涯上或许会有人觉得你很有个性而叫好,煤气公司电话公司不会因为觉得你很有个性而 免了你的帐单。当你很帅地炒掉了你的老板,当你很酷地挖苦了一番招聘的HR,账单还是要照付,只是你赚钱的时间更少了,除了你自己,没人受损失。

    我并不反对跳槽,但跳槽决不是解决问题的办法,而且频繁跳槽的后果是让人觉得没有忠诚度可言,而且不能安心工作。现在很多人从网上找工作,很多找工作 的网站常常给人出些馊主意,要知道他们是盈利性企业,当然要从自身盈利的角度来考虑,大家越是频繁跳槽频繁找工作他们越是生意兴隆,所以鼓动人们跳槽是他 们的工作。所以他们会常常告诉你,你拿的薪水少了,你享受的福利待遇差了,又是“薪情快报”又是“赞叹自由奔放的灵魂”。至于是否会因此让你不能安心,你 跳了槽是否解决问题,是否更加开心,那个,他们就不管了。

    要跳槽肯定是有问题,一般来说问题发生了,躲是躲不开的,很多人跳槽是因为这样或者那样的不开心,如果这种不开心,在现在这个公司不能解决,那么在下 一个公司多半也解决不掉。你必须相信,90%的情况下,你所在的公司并没有那么烂,你认为不错的公司也没有那么好。就像《围城》里说的,“城里的人拼命想 冲出来,而城外的人拼命想冲进去。”每个公司都有每个公司的问题,没有问题的公司是不存在的。换个环境你都不知道会碰到什么问题,与其如此,不如就在当下 把问题解决掉。很多问题当你真的想要去解决的时候,或许并没有那么难。有的时候你觉得问题无法解决,事实上,那只是“你觉得”

    人生的曲线应该是曲折向上的,偶尔会遇到低谷但大趋势总归是曲折向上的,而不是象脉冲波一样每每回到起点,我见过不少面试者,30多岁了,四五份工作 经历,每次多则3年,少则1年,30多岁的时候回到起点从一个初级职位开始干起,拿基本初级的薪水,和20多岁的年轻人一起竞争,不觉得有点辛苦么?这种 日子好过么?

    我非常不赞成在一个行业超过3年以后换行业,基本上,35岁以前我们的生存资本靠打拼,35岁以后生存的资本靠的就是积累,这种积累包括人际关系,经 验,人脉,口碑……如果常常更换行业,代表几年的积累付之东流,一切从头开始,如果换了两次行业,35岁的时候大概只有5年以下的积累,而一个没有换过行 业的人至少有了10年的积累,谁会占优势?工作到2-3年的时候,很多人觉得工作不顺利,好像到了一个瓶颈,心情烦闷,就想辞职,乃至换一个行业,觉得这 样所有一切烦恼都可以抛开,会好很多。

    其实这样做只是让你从头开始,到了时候还是会发生和原来行业一样的困难,熬过去就向上跨了一大步,要知道每个人都会 经历这个过程,每个人的职业生涯中都会碰到几个瓶颈,你熬过去了而别人没有熬过去你就领先了

    跑长跑的人会知道,开始的时候很轻松,但是很快会有第一次的 难受,但过了这一段又能跑很长一段,接下来会碰到第二次的难受,坚持过了以后又能跑一段,如此往复,难受一次比一次厉害,直到坚持不下去了。大多数人第一 次就坚持不了了,一些人能坚持到第二次,第三次虽然大家都坚持不住了,可是跑到这里的人也没几个了,这点资本足够你安稳活这一辈子了

    一份工作到两三年的时候,大部分人都会变成熟手,这个时候往往会陷入不断的重复,有很多人会觉得厌倦,有些人会觉得自己已经搞懂了一切,从而懒得去寻 求进步了。很多时候的跳槽是因为觉得失去兴趣了,觉得自己已经完成比赛了。其实这个时候比赛才刚刚开始,工作两三年的人,无论是客户关系,人脉,手下,和 领导的关系,在业内的名气……还都是远远不够的,但稍有成绩的人总是会自我感觉良好的,每个人都觉得自己跟客户关系铁得要命,觉得自己在业界的口碑好得很。其实可以肯定地说,一定不是,这个时候,还是要拿出前两年的干劲来,稳扎稳打,积累才刚刚开始

    你足够了解你的客户吗?你知道他最大的烦恼是什么吗?你足够了解你的老板么?你知道他最大的烦恼是什么吗?你足够了解你的手下么?你知道他最大的烦恼 是什么吗?如果你不知道,你凭什么觉得自己已经积累够了?如果你都不了解,你怎么能让他们帮你的忙,做你想让他们做的事情?如果他们不做你想让他们做的事 情,你又何来的成功?

    等待

      这是个浮躁的人们最不喜欢的话题,本来不想说这个话题,因为会引起太多的争论,而我又无意和人争论这些,但是考虑到对于职业生涯的长久规划,这是一个躲避不了的话题,还是决定写一写,不爱看的请离开吧。
    并不是每次闯红灯都会被汽车撞,并不是每个罪犯都会被抓到,并不是每个错误都会被惩罚,并不是每个贪官都会被枪毙,并不是你的每一份努力都会得到回报,并不是你的每一次坚持都会有人看到,并不是你每一点付出都能得到公正的回报,并不是你的每一个善意都能被理解……这个,就是世道。好吧,世道不够好,可 是,你有推翻世道的勇气么?如果没有,你有更好的解决办法么?有很多时候,人需要一点耐心,一点信心。每个人总会轮到几次不公平的事情,而通常,安心等待 是最好的办法

    有很多时候我们需要等待,需要耐得住寂寞,等待属于你的那一刻。周润发等待过,刘德华等待过,周星驰等待过,王菲等待过,张艺谋也等待过……看到了他 们如今的功成名就的人,你可曾看到当初他们的等待和耐心?你可曾看到金马奖影帝在街边摆地摊?你可曾看到德云社一群人在剧场里给一位观众说相声?你可曾看到周星驰的角色甚至连一句台词都没有?每一个成功者都有一段低沉苦闷的日子,我几乎能想象得出来他们借酒浇愁的样子,我也能想象得出他们为了生存而挣扎的 窘迫。在他们一生最中灿烂美好的日子里,他们渴望成功,但却两手空空,一如现在的你。没有人保证他们将来一定会成功,而他们的选择是耐住寂寞。如果当时的 他们总念叨着“成功只是属于特权阶级的”,你觉得他们今天会怎样?
    曾经我也不明白有些人为什么并不比我有能力却要坐在我的头上,年纪比我大就一定要当我的领导么?为什么有些烂人不需要努力就能赚钱?为什么刚刚改革开 放的时候的人能那么容易赚钱,而轮到我们的时候,什么事情都要正规化了?有一天我突然想,我还在上学的时候他们就在社会里挣扎奋斗了,他们在社会上奋斗积 累了十几二十年,我们新人来了,他们有的我都想要,我这不是在要公平,我这是在要抢劫。因为我要得太急,因为我忍不住寂寞。二十多岁的男人,没有钱,没有 事业,却有蓬勃的欲望

    人总是会遇到挫折的,人总是会有低潮的,人总是会有不被人理解的时候的,人总是有要低声下气的时候,这些时候恰恰是人生最关键的时候因为大家都会碰 到挫折,而大多数人过不了这个门槛,你能过,你就成功了。在这样的时刻,我们需要耐心等待,满怀信心地去等待,相信,生活不会放弃你,机会总会来的。至 少,你还年轻,你没有坐牢,没有生治不了的病,没有欠还不起的债。比你不幸的人远远多过比你幸运的人,你还怕什么?路要一步步走,虽然到达终点的那一步很 激动人心,但大部分的脚步是平凡甚至枯燥的,但没有这些脚步,或者耐不住这些平凡枯燥,你终归是无法迎来最后的那些激动人心。
    逆境,是上帝帮你淘汰竞争者的地方。要知道,你不好受,别人也不好受,你坚持不下去了,别人也一样,千万不要告诉别人你坚持不住了,那只能让别人获得坚持的信心,让竞争者看着你微笑的面孔,失去信心,退出比赛胜利属于那些有耐心的人

    在最绝望的时候,我会去看电影《The Pursuit of Happiness》《Jerry Maguire》,让自己重新鼓起勇气,因为,无论什么时候,我们总还是有希望。当所有的人离开的时候,我不失去希望,我不放弃。每天下班坐在车里,我喜欢哼着《隐形的翅膀》看着窗外,我知道,我在静静等待,等待属于我的那一刻。
    原贴里伊吉网友的话我很喜欢,抄录在这里:
    每个人都希望,自己是独一无二的特殊者
    含着金匙出生、投胎到好家庭、工作安排到电力局拿1w月薪这样的小概率事件,当然最好轮到自己
    红军长征两万五、打成右派反革命、胼手胝足牺牲尊严去奋斗,最好留给祖辈父辈和别人
    自然,不是每个吃过苦的人都会得到回报
    但是,任何时代,每一个既得利益者身后,都有他的祖辈父辈奋斗挣扎乃至流血付出生命的身影
    羡慕别人有个好爸爸,没什么不可以
    问题是,你的下一代,会有一个好爸爸吗?
    至于问到为什么不能有同样的赢面概率?我只能问:为什么物种竞争中,人和猴子不能有同样的赢面概率?
    物竞天择。猴子的灵魂不一定比你卑微,但你身后有几十万年的类人猿进化积淀。

    入对行,跟对人

      在中国,大概很少有人是一份职业做到底的,虽然如此,第一份工作还是有些需要注意的地方,有两件事情格外重要,第一件是入行,第二件事情是跟人。第一 份工作对人最大的影响就是入行,现代的职业分工已经很细,我们基本上只能在一个行业里成为专家,不可能在多个行业里成为专家。很多案例也证明即使一个人在一个行业非常成功,到另外一个行业,往往完全不是那么回事情,“你想改变世界,还是想卖一辈子汽水?”是乔布斯邀请百事可乐总裁约翰·斯考利加盟苹果时所说的话,结果这位在百事非常成功的约翰,到了苹果表现平平。其实没有哪个行业特别好,也没有哪个行业特别差,或许有报道说哪个行业的平均薪资比较高,但是 他们没说的是,那个行业的平均压力也比较大。看上去很美的行业一旦进入才发现很多地方其实并不那么完美,只是外人看不见。

    说实话,我自己都没有发大财,所以我的建议只是让人快乐工作的建议,不是如何发大财的建议,我们只讨论一般普通打工者的情况。我认为选择什么行业并没 有太大关系,看问题不能只看眼前。比如,从前年开始,国家开始整顿医疗行业,很多医药公司开不下去,很多医药行业的销售开始转行。其实医药行业的不景气是 针对所有公司的,并非针对一家公司,大家的日子都不好过,这个时候跑掉是非常不划算的,大多数正规的医药公司即使不做新生意撑个两三年总是能撑的,大多数 医药销售靠工资撑个两三年也是可以撑的,国家不可能永远捏着医药行业不放的,两三年以后光景总归还会好起来的,那个时候别人都跑了而你没跑,那时的日子应 该会好过很多。有的时候觉得自己这个行业不行了,问题是,再不行的行业,做得人少了也变成了好行业,当大家都觉得不好的时候,往往却是最好的时候。大家都 觉得金融行业好,金融行业门槛高不说,有多少人削尖脑袋要钻进去,竞争激励,进去以后还要时时提防,一个疏忽,就被后来的人给挤掉了,压力巨大,又如何谈 得上快乐?也就未必是“好”工作了。

    太阳能这个东西至今还不能进入实际应用的阶段,但是中国已经有7家和太阳能有关的公司在纽交所上市了,国美苏宁永乐其实是贸易型企业,也能上市,鲁泰 纺织连续10年利润增长超过50%,卖茶的一茶一座,卖衣服的海澜之家都能上市……其实选什么行业真的不重要,关键是怎么做。事情都是人做出来的,关键是人

    有一点是需要记住的,这个世界上,有史以来直到我们能够预见得到的未来,成功的人总是少数,有钱的人总是少数,大多数人是一般的,普通的,不太成功 的。因此,大多数人的做法和看法,往往都不是距离成功最近的做法和看法。因此大多数人说好的东西不见得好,大多数人说不好的东西不见得不好。大多数人都去 炒股的时候说明跌只是时间问题,大家越是热情高涨的时候,跌的日子越近。大多数人买房子的时候,房价不会涨,而房价涨的差不多的时候,大多数人才开始买房子。不会有这样一件事情让大家都变成功,发了财,历史上不曾有过,将来也不会发生。有些东西即使一时运气好得到了,还是会在别的时候别的地方失去的。


    年轻人在职业生涯的刚开始,尤其要注意的是,要做对的事情,不要让自己今后几十年的人生总是提心吊胆,更不值得为了一份工作赔上自己的青春年华。我的 公司是个不行贿的公司,以前很多人不理解,甚至自己的员工也不理解,不过如今,我们是同行中最大的企业,客户乐意和我们打交道,尤其是在国家打击腐败的时 候,每个人都知道我们做生意不给钱的名声,都敢于和我们做生意。而勇于给钱的公司,不是倒了,就是跑了,要不就是每天睡不好觉,人还是要看长远一点。很多 时候,看起来最近的路,其实是最远的路,看起来最远的路,其实是最近的路

    跟对人是说,入行后要跟个好领导好老师,刚进社会的人做事情往往没有经验,需要有人言传身教。对于一个人的发展来说,一个好领导是非常重要的。所谓“好”的标准,不是他让你少干活多拿钱,而是以下三个。

    首先,好领导要有宽广的心胸,如果一个领导每天都会发脾气,那几乎可以肯定他不是个心胸宽广的人,能发脾气的时候却不发脾气的领导,多半是非常厉害的 领导。中国人当领导最大的毛病是容忍不了能力比自己强的人,所以常常可以看到的一个现象是,领导很有能力,手下一群庸才或者手下一群闲人。如果看到这样的 环境,还是不要去的好。


    其次,领导要愿意从下属的角度来思考问题,这一点其实是从面试的时候就能发现的,如果这位领导总是从自己的角度来考虑问题,几乎不听你说什么,这就危 险了。从下属的角度来考虑问题并不代表同意下属的说法,但他必须了解下属的立场,下属为什么要这么想,然后他才有办法说服你,只关心自己怎么想的领导往往 难以获得下属的信服。

    第三,领导敢于承担责任,如果出了问题就把责任往下推,有了功劳就往自己身上揽,这样的领导不跟也罢。选择领导,要选择关键时刻能抗得住的领导,能够为下属的错误买单的领导,因为这是他作为领导的责任。
    有可能,你碰不到好领导,因为,中国的领导往往是屁股决定脑袋的领导,因为他坐领导的位置,所以他的话就比较有道理,这是传统观念官本位的误区,可能 有大量的这种无知无能的领导,只是,这对于你其实是好事,如果将来有一天你要超过他,你希望他比较聪明还是比较笨?相对来说这样的领导其实不难搞定,只是 你要把自己的身段放下来而已。多认识一些人,多和比自己强的人打交道,同样能找到好的老师,不要和一群同样郁闷的人一起控诉社会,控诉老板,这帮不上你, 只会让你更消极。和那些比你强的人打交道,看他们是怎么想的,怎么做的,学习他们,然后跟更强的人打交道。

    选择

      我们每天做的最多的事情,其实是选择,因此在谈职业生涯的时候不得不提到这个话题。
    我始终认为,在 很大的范围内,我们究竟会成为一个什么样的人,决定权在我们自己,每天我们都在做各种各样的选择,我可以不去写这篇文章,去别人的帖子拍拍砖头,也可以写 下这些文字,帮助别人的同时也整理自己的思路,我可以多注意一下格式让别人易于阅读,也可以写成一堆,我可以就这样发上来,也可以在发以前再看几遍,你可 以选择不刮胡子就去面试,也可以选择出门前照照镜子……每天,每一刻我们都在做这样那样的决定,我们可以漫不经心,也可以多花些心思,成千上万的小选择累 计起来,就决定了最终我们是个什么样的人。

    从某种意义上来说我们的未来不是别人给的,是我们自己选择的,很多人会说我命苦啊,没得选择啊,如果你认为“去微软还是去IBM”“上清华还是上北 大”“当销售副总还是当厂长”这种才叫选择的话,的确你没有什么选择,大多数人都没有什么选择。但每天你都可以选择是否为客户服务更周到一些,是否对同事 更耐心一些,是否把工作做得更细致一些,是否把情况了解得更清楚一些,是否把不清楚的问题再弄清楚一些……你也可以选择在是否在痛苦中继续坚持,是否抛弃 掉自己的那些负面的想法,是否原谅一个人的错误,是否相信我在这里写下的这些话,是否不要再犯同样的错误……生活每天都在给你选择的机会,每天都在给你改 变自己人生的机会,你可以选择赖在地上撒泼打滚,也可以选择咬牙站起来。你永远都有选择。有些选择不是立竿见影的,需要累积,比如农民可以选择自己常常去 浇地,也可以选择让老天去浇地,诚然你今天浇水下去苗不见得今天马上就长出来,但常常浇水,大部分苗终究会长出来的,如果你不浇,收成一定很糟糕。

    每天生活都在给你机会,他不会给你一叠现金也不会拱手送你个好工作,但实际上,他还是在给你机会。我的家庭是一个普通的家庭,没有任何了不起的社会关 系,我的父亲在大学毕业以后就被分配到了边疆,那个小县城只有一条马路,他们那一代人其实比我们更有理由抱怨,他们什么也没得到,年轻的时候文化大革命, 书都没得读,支援边疆插队落户,等到老了,却要给年轻人机会了。他有足够的理由像成千上万那样的青年一样坐在那里抱怨生不逢时,怨气冲天。然而在分配到边 疆的十年之后,国家恢复招研究生,他考回了原来的学校。研究生毕业,他被分配到了安徽一家小单位里,又是3年以后,国家第一届招收博士生,他又考回了原来 的学校,成为中国第一代博士,那时的他比现在的我年纪还大。生活并没有放弃他,他也没有放弃生活。10年的等待,他做了他自己的选择,他没有放弃,他没有 破罐子破摔,所以时机到来的时候,他改变了自己的人生。你最终会成为什么样的人,就决定在你的每个小小的选择之间。

    你选择相信什么?你选择和谁交朋友?你选择做什么?你选择怎么做?……我们面临太多的选择,而这些选择当中,意识形态层面的选择又远比客观条件的选择 来得重要得多,比如选择做什么产品其实并不那么重要,而选择怎么做才重要。选择用什么人并不重要,而选择怎么带这些人才重要。大多数时候选择客观条件并不 要紧,大多数关于客观条件的选择并没有对错之分,要紧的是选择怎么做。一个大学生毕业了,他要去微软也好,他要卖猪肉也好,他要创业也好,他要做游戏代练 也好,只要不犯法,不害人,都没有什么关系,要紧的是,选择了以后,怎么把事情做好

    除了这些,你还可以选择时间和环境,比如,你可以选择把这辈子最大的困难放在最有体力最有精力的时候,也可以走一步看一步,等到了40岁再说,只是到 了40多岁,那正是一辈子最脆弱的时候,上有老下有小,如果在那个时候碰上了职业危机,实在是一件很苦恼的事情。与其如此不如在20多岁30多岁的时候吃 点苦,好让自己脆弱的时候活得从容一些。你可以选择在温室里成长,也可以选择到野外磨砺,你可以选择在办公室吹冷气的工作,也可以选择40度的酷热下,去 见你的客户,只是,这一切最终会累积起来,引导你到你应得的未来。

    我不敢说所有的事情你都有得选择,但是绝大部分事情你有选择,只是往往你不把这当作一种选择。认真对待每一次选择,才会有比较好的未来。

    选择职业

    职业的选择,总的来说,无非就是销售、市场、客服、物流、行政、人事、财务、技术、管理几个大类,有个有趣的现象就是,500强的CEO当中最多的是 销售出身,第二多的人是财务出身,这两者加起来大概超过95%。现代IT行业也有技术出身成为老板的,但实际上,后来他们还是从事了很多销售和市场的工 作,并且表现出色,公司才获得了成功,完全靠技术能力成为公司老板的,几乎没有。这是有原因的,因为销售就是一门跟人打交道的学问,而管理其实也是跟人打 交道的学问,这两者之中有很多相通的东西,他们的共同目标就是“让别人去做某件特定的事情。”而财务则是从数字的层面了解生意的本质,从宏观上看待生意的 本质,对于一个生意是否挣钱,是否可以正常运作有着最深刻的认识。

    公司小的时候是销售主导公司,而公司大的时候是财务主导公司
    销售的局限性在于只看人情不看数字,财务的局限性在于只看数字不看人情。公司初期,运营 成本低,有订单就活得下去,跟客户也没有什么谈判的条件,别人肯给生意做已经谢天谢地了这个时候订单压倒一切,客户的要求压倒一切,所以当然要顾人情。 公司大了以后,一切都要规范化,免得因为不规范引起一些不必要的风险,同时运营成本也变高,必须提高利润率,把有限的资金放到最有产出的地方。对于上市公 司来说,股东才不管你客户是不是最近出国,最近是不是那个省又在搞严打,到了时候就要把业绩拿出来,拿不出来就抛股票,这个时候就是数字压倒一切。

    前两天听到有人说一句话觉得很有道理,开始的时候我们想“能做什么?”,等到公司做大了有规模了,我们想“不能做什么。”很多人在工作中觉得为什么领导这么保守,这也不行那也不行,错过很多机会。很多时候是因为,你还年轻,你想的是“能做什么”,而作为公司领导要考虑的方面很多,他比较关心“不能做什 么”。

    我并非鼓吹大家都去做销售或者财务,究竟选择什么样的职业,和你究竟要选择什么样的人生有关系,有些人就喜欢下班按时回家,看看书听听音乐,那也挺 好,但就不适合找个销售的工作了,否则会是折磨自己。有些人就喜欢出风头,喜欢成为一群人的中心,如果选择做财务工作,大概也干不久,因为一般老板不喜欢 财务太积极,也不喜欢财务话太多。先想好自己要过怎样的人生,再决定要找什么样的职业。有很多的不快乐,其实是源自不满足,而不满足,很多时候是源自于心 不定,而心不定则是因为不清楚究竟自己要什么,不清楚要什么的结果就是什么都想要,结果什么都没得到

    我想,我们还是因为生活而工作,不是因为工作而生活,生活是最要紧的,工作只是生活中的一部分。我总是觉得生活的各方面都是相互影响的,如果生活本身一团乱麻,工作也不会顺利。所以要有娱乐、要有社交、要锻炼身体,要有和睦的家庭……最要紧的,要开心,我的两个销售找我聊天,一肚子苦水,我问他们,2 年以前,你什么都没有,工资不高,没有客户关系,没有业绩,处于被开的边缘,现在的你比那时条件好了很多,为什么现在却更加不开心了?如果你做得越好越不开心,那你为什么还要工作?首先的首先,人还是要让自己高兴起来,让自己心态好起来,这种发自内心的改变会让你更有耐心,更有信心,更有气质,更能包 容……否则,看看镜子里的你,你满意么?
    有人会说,你说得容易,我每天加班,不加班老板就会把我炒掉,每天累得要死,哪有时间娱乐、社交、锻炼?那是人们把目标设定太高的缘故,如果你还在动不动就会被老板炒掉的边缘,那么你当然不能设立太高的目标,难道你还想每天去打高尔夫?你没时间去健身房锻炼身体,但是上下班的时候多走几步可以吧,有楼梯的时候走走楼梯不走电梯可以吧?办公的间隙扭扭脖子拉拉肩膀做做俯卧撑可以吧?谁规定锻炼就一定要拿出每天2个小时去健身房?你没时间社交,每月参加郊游一次可以吧,周末去参加个什么音乐班,绘画班之类的可以吧,去尝试认识一些同行,和他们找机会交流交流可以吧?开始的时候总是有些难的,但迈出这一步就会向良性循环的方向发展。而每天工作得很苦闷,剩下的时间用来咀嚼苦闷,只会陷入恶性循环,让生活更加糟糕。
  • 本科差点没能毕业,工作五年后年收入过百万

    2008-07-04 17:42:13

    这是我听到的故事,主角就称呼他小明吧,小明的口头禅是“能写代码的人太多了,真正牛的是能把代码换成钱的人。”

    小明是一个很聪明的人,不过不爱学习,只是在某重点大学里混日子,英语连续补考了3次,四级到大四刚好过,成绩也很差,是年级最后10名

    ,因此差点没能毕业,不过这一切危机都在小明超强的活动能力下化为无形。在大四的毕业设计时,小明找了一个同乡的老师,这个老师有个

    侄子要考某重点高中,小明利用自己的关系,帮这个小孩上了重点高中,因此毕业设计没费多少力气就顺利拿了个A+。

    结束大学生活,小明开始了竞争激烈的社会生活,按理说小明在大学基本没学到什么技术,要找工作应该很难。但是早在大一时小明就计划好

    了,小明找了一个学习很好的同乡师兄,两人混的很熟。小明毕业后,他的师兄正在上海某大企业担当项目经理,小明很容易就进入该企业工

    作了,当时工资3k。

    对小明来说,3k远远无法满足他的胃口,但他发现了另一件好事,他的部长同样也是他的老乡。不知道是不是都是东北人的缘故,三个同乡都

    心心相惜,小明更是以惊人的酒量征服了另两个同乡,也因此成为了部长和项目经理的亲信。

    小明注定发展道路和其他同事是不同的。虽然一开始小明的职位是软件工程师,但是小明的心思并没有放在开发上,更多的小明想尽办法尽量

    跟着项目经理一起与供货商以及客户交流。因为小明头脑聪明,反应敏捷,而且酒量惊人,的确讨人喜欢,几乎所有的项目,项目经理和部长

    都把他带在身边。小明很快就学会了一个项目经理该干的活。

    小明虽然技术不行,但是他很有想法,他很清楚如果自己想当项目经理,就需要踢开目前的师兄,当然陷害师兄的事情他是不会做的,一个偶

    然的电话给了他一个机会。小明偶然的接到一个猎头的电话,心里突然有了想法,这个女猎头注定无法逃脱小明的五指山,很快女猎头就成了

    小明亲密的朋友,而且帮小明物色了一个很好的部长职位,这个位置是给小明的?不是,通过小明的穿针引线,小明的师兄应聘了该职位,临

    走时还特意酬谢了小明。就这样,小明终于踢开了自己的挡脚石,同时小明也甩开了女猎头的纠缠,按照小明的说法是这个女的太会花钱了,

    至于真正的原因,大家自己想吧。

    踢开项目经理,小明会不会给他人做嫁衣呢?毕竟小明的工作资历短,项目经理的职位怎么排都轮不到他啊。不会,小明有十足的把握,通过

    部长的“推荐”(理由只有小明和客户交流过,目前没有其他人能顶替这个位置,而事实也确实如此),小明顺利当上了项目经理,工作一年

    ,工资从3k-》6.5k。

    当上项目经理,小明的工作性质发生了变化,编程已经不是小明该做的事情了,这些事情交给手下做就行了,小明有了新的目标。靠工资生活

    对小明来说是笑谈,为了能快速敛财,小明开始接一些私活来干,这些私活都不是小明做,小明只是接活的人,真正干活的是小明拉入伙的手

    下或者朋友。这些私活到底给小明赚了多少钱我们就不知道了,不过小明在担任项目经理的两年时间里,首付买了一套150平米的房子。项目经

    理两年,买房一套,工资从6.5k-》7k。

    按理说小明的发展已经够快了,但小明还想更快,两年后小明就跳槽到一家软件外包公司担当项目经理,工资从7k-》15k。小明的工资能如此

    迅速的飞涨,是因为小明的技术很强么?小明的能力很强是无需置疑的,但不是开发技术,小明一直在不断扩展自己的人脉,并且认识了某外

    企一个很有实力的人物。而外包公司看中的正是小明的人脉关系,技术比小明强的人海了去,但没有一个能像小明这样带着客户过来的。小明

    就这样轻松的月薪过万,但小明的目标不是如此,小明开始研究外包公司的运作流程,为今后做打算。

    在外包公司工作一年以后,小明突然辞职,找了两个合伙人,开始创业了。这两个合伙人都是什么样的人呢?两个合伙人的能力如何先暂且不

    说,背景实力却不容忽视,一个是政府高官的亲戚,另一个的叔叔在某国有银行担任高职。一个有权,一个有钱,而小明则能带来他们所缺的

    技术,三者一拍即合,共同成立一家软件外包公司,对象正是近水楼台的政府部门。公司负责人是有权的人,管钱的人是有钱的人,而小明则

    是公司的技术总监,工资20k,当然这已不是小明的主要收入,每年公司的分红就将近百万。辞职创业一年,年收入过百万。

    故事到此就告一段落了。听完这个故事,我的头脑里一直在回响那句话“能写代码的人太多了,真正牛的是能把代码换成钱的人。”
  • 【转贴】理解Java ClassLoader机制

    2008-06-24 12:22:39

    原文链接:http://www.sharecenter.net/archiver/tid-109152.html

    当JVM(Java虚拟机)启动时,会形成由三个类加载器组成的初始类加载器层次结构:

           bootstrap classloader
                    |
           extension classloader
                    |
           system classloader

    bootstrap classloader -引导(也称为原始)类加载器,它负责加载Java的核心类。在Sun的JVM中,在执行java的命令中使用-Xbootclasspath选项或使用- D选项指定sun.boot.class.path系统属性值可以指定附加的类。这个加载器的是非常特殊的,它实际上不是 java.lang.ClassLoader的子类,而是由JVM自身实现的。大家可以通过执行以下代码来获得bootstrap classloader加载了那些核心类库:
       URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
       for (int i = 0; i < urls.length; i++) {
         System.out.println(urls.toExternalform());
       }
    在我的计算机上的结果为:
    文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/dom.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/sax.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xalan-2.3.1.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xercesImpl-2.0.0.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xml-apis.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xsltc.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/rt.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/i18n.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/sunrsasign.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/jsse.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/jce.jar
    文件:/C:/j2sdk1.4.1_01/jre/lib/charsets.jar
    文件:/C:/j2sdk1.4.1_01/jre/classes
    这时大家知道了为什么我们不需要在系统属性CLASSPATH中指定这些类库了吧,因为JVM在启动的时候就自动加载它们了。

    extension classloader -扩展类加载器,它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或者由java.ext.dirs系统属性指定的)中JAR的类包。这为引入除Java核心类以外的新功能提供了一个标准机制。因为默认的扩展目录对所有从同一个JRE中启动的JVM都是通用的,所以放入这个目录的 JAR类包对所有的JVM和system classloader都是可见的。在这个实例上调用方法getParent()总是返回空值null,因为引导加载器bootstrap classloader不是一个真正的ClassLoader实例。所以当大家执行以下代码时:
       System.out.println(System.getProperty("java.ext.dirs"));
       ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent();
       System.out.println("the parent of extension classloader : "+extensionClassloader.getParent());
    结果为:
    C:\j2sdk1.4.1_01\jre\lib\ext
    the parent of extension classloader : null
    extension classloader是system classloader的parent,而bootstrap classloader是extension classloader的parent,但它不是一个实际的classloader,所以为null。

    system classloader -系统(也称为应用)类加载器,它负责在JVM被启动时,加载来自在命令java中的-classpath或者java.class.path系统属性或者 CLASSPATH*作系统属性所指定的JAR类包和类路径。总能通过静态方法ClassLoader.getSystemClassLoader()找到该类加载器。如果没有特别指定,则用户自定义的任何类加载器都将该类加载器作为它的父加载器。执行以下代码即可获得:
       System.out.println(System.getProperty("java.class.path"));
    输出结果则为用户在系统属性里面设置的CLASSPATH。
    classloader 加载类用的是全盘负责委托机制。所谓全盘负责,即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入;委托机制则是先让parent(父)类加载器 (而不是super,它与parent classloader类不是继承关系)寻找,只有在parent找不到的时候才从自己的类路径中去寻找。此外类加载还采用了cache机制,也就是如果 cache中保存了这个Class就直接返回它,如果没有才从文件中读取和转换成Class,并存入cache,这就是为什么我们修改了Class但是必须重新启动JVM才能生效的原因。


    每个ClassLoader加载Class的过程是:
    1.检测此Class是否载入过(即在cache中是否有此Class),如果有到8,如果没有到2
    2.如果parent classloader不存在(没有parent,那parent一定是bootstrap classloader了),到4
    3.请求parent classloader载入,如果成功到8,不成功到5
    4.请求jvm从bootstrap classloader中载入,如果成功到8
    5.寻找Class文件(从与此classloader相关的类路径中寻找)。如果找不到则到7.
    6.从文件中载入Class,到8.
    7.抛出ClassNotFoundException.
    8.返回Class.

    其中5.6步我们可以通过覆盖ClassLoader的findClass方法来实现自己的载入策略。甚至覆盖loadClass方法来实现自己的载入过程。

    类加载器的顺序是:
    先是bootstrap classloader,然后是extension classloader,最后才是system classloader。大家会发现加载的Class越是重要的越在靠前面。这样做的原因是出于安全性的考虑,试想如果system classloader“亲自”加载了一个具有破坏性的“java.lang.System”类的后果吧。这种委托机制保证了用户即使具有一个这样的类,也把它加入到了类路径中,但是它永远不会被载入,因为这个类总是由bootstrap classloader来加载的。大家可以执行一下以下的代码:
       System.out.println(System.class.getClassLoader());
    将会看到结果是null,这就表明java.lang.System是由bootstrap classloader加载的,因为bootstrap classloader不是一个真正的ClassLoader实例,而是由JVM实现的,正如前面已经说过的。

    下面就让我们来看看JVM是如何来为我们来建立类加载器的结构的:
    sun.misc.Launcher,顾名思义,当你执行java命令的时候,JVM会先使用bootstrap classloader载入并初始化一个Launcher,执行下来代码:
      System.out.println("the Launcher's classloader is "+sun.misc.Launcher.getLauncher().getClass().getClassLoader());
    结果为:
      the Launcher's classloader is null (因为是用bootstrap classloader加载,所以class loader为null)
    Launcher 会根据系统和命令设定初始化好class loader结构,JVM就用它来获得extension classloader和system classloader,并载入所有的需要载入的Class,最后执行java命令指定的带有静态的main方法的Class。extension classloader实际上是sun.misc.Launcher$ExtClassLoader类的一个实例,system classloader实际上是sun.misc.Launcher$AppClassLoader类的一个实例。并且都是 java.net.URLClassLoader的子类。

    让我们来看看Launcher初试化的过程的部分代码。

    Launcher的部分代码:
    public class Launcher  {
       public Launcher() {
           ExtClassLoader extclassloader;
           try {
               //初始化extension classloader
               extclassloader = ExtClassLoader.getExtClassLoader();
           } catch(IOException ioexception) {
               throw new InternalError("Could not create extension class loader");
           }
           try {
               //初始化system classloader,parent是extension classloader
               loader = AppClassLoader.getAppClassLoader(extclassloader);
           } catch(IOException ioexception1) {
               throw new InternalError("Could not create application class loader");
           }
           //将system classloader设置成当前线程的context classloader(将在后面加以介绍)
           Thread.currentThread().setContextClassLoader(loader);
           ......
       }
       public ClassLoader getClassLoader() {
           //返回system classloader
           return loader;
       }
    }

    extension classloader的部分代码:
    static class Launcher$ExtClassLoader extends URLClassLoader {

       public static Launcher$ExtClassLoader getExtClassLoader()
           throws IOException
       {
           File afile[] = getExtDirs();
           return (Launcher$ExtClassLoader)AccessController.doPrivileged(new Launcher$1(afile));
       }
      private static File[] getExtDirs() {
           //获得系统属性“java.ext.dirs”
           String s = System.getProperty("java.ext.dirs");
           File afile[];
           if(s != null) {
               StringTokenizer stringtokenizer = new StringTokenizer(s, File.pathSeparator);
               int i = stringtokenizer.countTokens();
               afile = new File;
               for(int j = 0; j < i; j++)
                   afile[j] = new File(stringtokenizer.nextToken());

           } else {
               afile = new File[0];
           }
           return afile;
       }
    }

    system classloader的部分代码:
    static class Launcher$AppClassLoader extends URLClassLoader
    {

       public static ClassLoader getAppClassLoader(ClassLoader classloader)
           throws IOException
       {
           //获得系统属性“java.class.path”
           String s = System.getProperty("java.class.path");
           File afile[] = s != null ? Launcher.access$200(s) : new File[0];
           return (Launcher$AppClassLoader)AccessController.doPrivileged(new Launcher$2(s, afile, classloader));
       }
    }

    看了源代码大家就清楚了吧,extension classloader是使用系统属性“java.ext.dirs”设置类搜索路径的,并且没有parent。system classloader是使用系统属性“java.class.path”设置类搜索路径的,并且有一个parent classloader。Launcher初始化extension classloader,system classloader,并将system classloader设置成为context classloader,但是仅仅返回system classloader给JVM。

      这里怎么又出来一个context classloader呢?它有什么用呢?我们在建立一个线程Thread的时候,可以为这个线程通过setContextClassLoader方法来指定一个合适的classloader作为这个线程的context classloader,当此线程运行的时候,我们可以通过getContextClassLoader方法来获得此context classloader,就可以用它来载入我们所需要的Class。默认的是system classloader。利用这个特性,我们可以“打破”classloader委托机制了,父classloader可以获得当前线程的context classloader,而这个context classloader可以是它的子classloader或者其他的classloader,那么父classloader就可以从其获得所需的 Class,这就打破了只能向父classloader请求的限制了。这个机制可以满足当我们的classpath是在运行时才确定,并由定制的 classloader加载的时候,由system classloader(即在jvm classpath中)加载的class可以通过context classloader获得定制的classloader并加载入特定的class(通常是抽象类和接口,定制的classloader中是其实现),例如web应用中的servlet就是用这种机制加载的.


    好了,现在我们了解了classloader的结构和工作原理,那么我们如何实现在运行时的动态载入和更新呢?只要我们能够动态改变类搜索路径和清除classloader的cache中已经载入的Class就行了,有两个方案,一是我们继承一个classloader,覆盖loadclass方法,动态的寻找Class文件并使用defineClass方法来;另一个则非常简单实用,只要重新使用一个新的类搜索路径来new一个classloader就行了,这样即更新了类搜索路径以便来载入新的Class,也重新生成了一个空白的cache(当然,类搜索路径不一定必须更改)。噢,太好了,我们几乎不用做什么工作,java.netURLClassLoader正是一个符合我们要求的classloader!我们可以直接使用或者继承它就可以了!

    这是j2se1.4 API的doc中URLClassLoader的两个构造器的描述:
    URLClassLoader(URL[] urls)
             Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader.
    URLClassLoader(URL[] urls, ClassLoader parent)
             Constructs a new URLClassLoader for the given URLs.
    其中URL[] urls就是我们要设置的类搜索路径,parent就是这个classloader的parent classloader,默认的是system classloader。


    好,现在我们能够动态的载入Class了,这样我们就可以利用newInstance方法来获得一个Object。但我们如何将此Object造型呢?可以将此Object造型成它本身的Class吗?

    首先让我们来分析一下java源文件的编译,运行吧!javac命令是调用“JAVA_HOME/lib/tools.jar”中的“com.sun.tools.javac.Main”的compile方法来编译:

       public static int compile(String as[]);

       public static int compile(String as[], PrintWriter printwriter);

    返回0表示编译成功,字符串数组as则是我们用javac命令编译时的参数,以空格划分。例如:
    javac -classpath c:\foo\bar.jar;. -d c:\ c:\Some.java
    则字符串数组as为{"-classpath","c:\\foo\\bar.jar;.","-d","c:\\","c:\\Some.java"},如果带有PrintWriter参数,则会把编译信息出到这个指定的printWriter中。默认的输出是System.err。

    其中 Main是由JVM使用Launcher初始化的system classloader载入的,根据全盘负责原则,编译器在解析这个java源文件时所发现的它所依赖和引用的所有Class也将由system classloader载入,如果system classloader不能载入某个Class时,编译器将抛出一个“cannot resolve symbol”错误。

    所以首先编译就通不过,也就是编译器无法编译一个引用了不在CLASSPATH中的未知Class的java源文件,而由于拼写错误或者没有把所需类库放到CLASSPATH中,大家一定经常看到这个“cannot resolve symbol”这个编译错误吧!

    其次,就是我们把这个Class放到编译路径中,成功的进行了编译,然后在运行的时候不把它放入到CLASSPATH中而利用我们自己的 classloader来动态载入这个Class,这时候也会出现“java.lang.NoClassDefFoundError”的违例,为什么呢?

    我们再来分析一下,首先调用这个造型语句的可执行的Class一定是由JVM使用Launcher初始化的system classloader载入的,根据全盘负责原则,当我们进行造型的时候,JVM也会使用system classloader来尝试载入这个Class来对实例进行造型,自然在system classloader寻找不到这个Class时就会抛出“java.lang.NoClassDefFoundError”的违例。

    OK,现在让我们来总结一下,java文件的编译和Class的载入执行,都是使用Launcher初始化的system classloader作为类载入器的,我们无法动态的改变system classloader,更无法让JVM使用我们自己的classloader来替换system classloader,根据全盘负责原则,就限制了编译和运行时,我们无法直接显式的使用一个system classloader寻找不到的Class,即我们只能使用Java核心类库,扩展类库和CLASSPATH中的类库中的Class。

    还不死心!再尝试一下这种情况,我们把这个Class也放入到CLASSPATH中,让system classloader能够识别和载入。然后我们通过自己的classloader来从指定的class文件中载入这个Class(不能够委托 parent载入,因为这样会被system classloader从CLASSPATH中将其载入),然后实例化一个Object,并造型成这个Class,这样JVM也识别这个Class(因为 system classloader能够定位和载入这个Class从CLASSPATH中),载入的也不是CLASSPATH中的这个Class,而是从 CLASSPATH外动态载入的,这样总行了吧!十分不幸的是,这时会出现“java.lang.ClassCastException”违例。

    为什么呢?我们也来分析一下,不错,我们虽然从CLASSPATH外使用我们自己的classloader动态载入了这个Class,但将它的实例造型的时候是JVM会使用system classloader来再次载入这个Class,并尝试将使用我们的自己的classloader载入的Class的一个实例造型为system classloader载入的这个Class(另外的一个)。大家发现什么问题了吗?也就是我们尝试将从一个classloader载入的Class的一个实例造型为另外一个classloader载入的Class,虽然这两个Class的名字一样,甚至是从同一个class文件中载入。但不幸的是JVM 却认为这个两个Class是不同的,即JVM认为不同的classloader载入的相同的名字的Class(即使是从同一个class文件中载入的)是不同的!这样做的原因我想大概也是主要出于安全性考虑,这样就保证所有的核心Java类都是system classloader载入的,我们无法用自己的classloader载入的相同名字的Class的实例来替换它们的实例。

    看到这里,聪明的读者一定想到了该如何动态载入我们的Class,实例化,造型并调用了吧!

    那就是利用面向对象的基本特性之一的多形性。我们把我们动态载入的Class的实例造型成它的一个system classloader所能识别的父类就行了!这是为什么呢?我们还是要再来分析一次。当我们用我们自己的classloader来动态载入这我们只要把这个Class的时候,发现它有一个父类Class,在载入它之前JVM先会载入这个父类Class,这个父类Class是system classloader所能识别的,根据委托机制,它将由system classloader载入,然后我们的classloader再载入这个Class,创建一个实例,造型为这个父类Class,注意了,造型成这个父类 Class的时候(也就是上溯)是面向对象的java语言所允许的并且JVM也支持的,JVM就使用system classloader再次载入这个父类Class,然后将此实例造型为这个父类Class。大家可以从这个过程发现这个父类Class都是由 system classloader载入的,也就是同一个class loader载入的同一个Class,所以造型的时候不会出现任何异常。而根据多形性,调用这个父类的方法时,真正执行的是这个Class(非父类 Class)的覆盖了父类方法的方法。这些方法中也可以引用system classloader不能识别的Class,因为根据全盘负责原则,只要载入这个Class的classloader即我们自己定义的 classloader能够定位和载入这些Class就行了。

    这样我们就可以事先定义好一组接口或者基类并放入CLASSPATH中,然后在执行的时候动态的载入实现或者继承了这些接口或基类的子类。还不明白吗?让我们来想一想Servlet吧,web application server能够载入任何继承了Servlet的Class并正确的执行它们,不管它实际的Class是什么,就是都把它们实例化成为一个Servlet Class,然后执行Servlet的init,doPost,doGet和destroy等方法的,而不管这个Servlet是从web- inf/lib和web-inf/classes下由system classloader的子classloader(即定制的classloader)动态载入。说了这么多希望大家都明白了。在applet,ejb等容器中,都是采用了这种机制.

    对于以上各种情况,希望大家实际编写一些example来实验一下。

    最后我再说点别的, classloader虽然称为类加载器,但并不意味着只能用来加载Class,我们还可以利用它也获得图片,音频文件等资源的URL,当然,这些资源必须在CLASSPATH中的jar类库中或目录下。我们来看API的doc中关于ClassLoader的两个寻找资源和Class的方法描述吧:
            public URL getResource(String name)
            用指定的名字来查找资源,一个资源是一些能够被class代码访问的在某种程度上依赖于代码位置的数据(图片,音频,文本等等)。
                   一个资源的名字是以'/'号分隔确定资源的路径名的。
                   这个方法将先请求parent classloader搜索资源,如果没有parent,则会在内置在虚拟机中的classloader(即bootstrap classloader)的路径中搜索。如果失败,这个方法将调用findResource(String)来寻找资源。
            public static URL getSystemResource(String name)
                   从用来载入类的搜索路径中查找一个指定名字的资源。这个方法使用system class loader来定位资源。即相当于ClassLoader.getSystemClassLoader().getResource(name)。

    例如:
       System.out.println(ClassLoader.getSystemResource("java/lang/String.class"));
    的结果为:
       jar:文件:/C:/j2sdk1.4.1_01/jre/lib/rt.jar!/java/lang/String.class
    表明String.class文件在rt.jar的java/lang目录中。
    因此我们可以将图片等资源随同Class一同打包到jar类库中(当然,也可单独打包这些资源)并添加它们到class loader的搜索路径中,我们就可以无需关心这些资源的具体位置,让class loader来帮我们寻找了!

734/4<1234
Open Toolbar