java程序服务脚本

 

windows下,为了预防系统重启导致程序被关闭,我们的java程序需要注册为系统服务,如果模块程序较多,而且有启动先后顺序的限制,需要编写bat脚本来控制启动顺序。
首先要了解一下windows bat脚本语法,详情参见这篇文章:[[

如果没有启动顺序要求,应该把模块注册为系统服务,将bat注册为系统服务,可以用如下两个软件实现:
使用Bat_To_Exe_Converter 将bat转化为exe,下载:
http://www.jb51.net/softs/21398.html

,还有一个附带的好处,无法查看bat文件的源代码了。使用srvinstw.exe 将exe注册为系统服务,下载:http://www.jb51.net/softs/21399.html
因为都是图形界面,就无须多解释了。注册成功之后,到控制面板->管理工具->服务里面就可以看到你新注册的服务了。
添加为计划任务也是一个不错的选择。

还有一个解决方法,就是设置组策略,运行:gpedit.msc 系统策略,启动里面添加bat文件

如果需要修改java程序的进程名,需要在jdk的bin目录复制一份java.exe,名称改为你需要的进程名,然后在启动java程序的脚本中把java ****中java改为你所要修改的进程名,其实就是用那个多余的java.exe副本启动程序,使得进程名得到修改。

写在2012的2011,不一样的2011

2011年对我来说是很艰难,很复杂,很沉重的一年。

这一年里我面临了太多的危机,太多的机会,太多的抉择。迷惘过,兴奋过,失望过,绝望过,崩溃过,我也在这一年里面完成了从IT农民工到管理者再到创业者的转变。如果很多年后,我一战成名,或者一败涂地,2011必然成为一个相当关键的转折点。

 

就业or创业

 

3月开春的时候,我很迷惘,一直在犹豫,是要否定自己一年前的决定,离开小公司到大公司去从头做起,还是坚持下去,做出点成绩来。在去上海出差的时候,我跟老板摊牌,把我一开始的计划和想法都分享了,还有辞职的原因。他很惊讶,但惊讶的不是我想辞职,而是我当初选择留下的理由和想法。他对我说:“像你这种年纪能这样敢想敢做,有想法有能力是很难得的。如果有一天我公司倒闭了,我会认为有一个很大的原因是没有把你的才能挖掘出来。现在我们确实面临困境,但是我一直认为,事情都是人在做,天在看。如果你现在就放弃去打工,你很难会再有这样的机会,你是做一番事情的人,我不希望你成为伤仲永”。

 

人在做,天在看,天上从来不掉馅饼,机会从来都只给又准备的人抓住。只有你先坚持不懈的努力去做,机会和希望才有可能出现。所以我决定再坚持3个月,在这3个月里面我要寻找一个答案:我到底是适合就业还是创业?

 

为了寻找这个答案,我去了一趟北京,参加了人人网和北京赛仕的面试。过硬的技术底子和非一般的经验让我毫无悬念的都通过了,可是offer却不如人意,待遇没有达到预期是一方面,主要是工作的内容让我感觉很枯燥无味。我意识到我在找工作这方面一直都处于很尴尬的局面,大型企业由于专业和资历限制进不去,中意的中小型企业又找不到(这个跟找女朋友一个道理,呵呵)。如果找不到一个适合你的企业,那就创造一个好了,我突然有了这个想法。因为我想到大企业的理由就是要学习技术、积累人脉和等待机会创业,最终的目标还是创业。因为自己还有一个叫做理想的东西藏在灵魂的深处——做一番有意义的属于自己的事业。只要这个理想还没死,我都不会老老实实打工。当然,也有一半是因为我先天不足,不具备被那些明星企业青睐的资格,我被这个社会,这个体制所排挤,成为了这个体制下的一个牺牲品。这种缺陷心理,更加刺激了我创业的欲望。

 

创业是一场赌博,我的赌注就是我这几年的青春,那是我的资本,除此之外,我一无所有,没什么可以输的了。我不去跟大温拿比年薪,不去跟公务员比安稳,我只要一步一步的去追随我那愚蠢的理想、偷来的理想。从2008年以来,我就一直在思考,一直在寻找我真正想要追求的东西,真正渴望的东西,我命中注定要做的事情。我走过弯路,犯过错,磕磕碰碰的走到今天,可是我至今还不敢断言我已经找到了,但我只知道,只要方向没错,坚持寻找,总有一天会找到的,正如乔布斯所说:“寻找你喜欢做的事情,找不到不要紧,要坚持寻找”。13年的中国教育,给我带来了尴尬的人生,我不想再过下去,要么失败,要么成功,我不需要第三种结果。我要的是一个过程,一段冒险的经历,一个我日后回首过往,可以回味的拼搏故事。

 

机会与诱惑

 

从4月份开始,我就开始和杜老板一起四处奔波,寻找合作方和投资方。我们意识到,凭我们自己是无法度过难关的,即使度过了,也后面的发展也成问题。多个朋友多条路嘛,目前这个经济环境,小公司是很难生存的,闭门造车必然是死路一条。因此我们从过朋友介绍,找到了梅和陈。他们是从一个公司带着项目跳槽出来创业的两个销售人员,他们看到了我们产品在证券行业是有市场的,所以就跟我们谈论合作的事情。一开始,他们的资金来源就有点灰色,后来牵涉的人也越来越多,各行各业的,移动应用,搜索引擎,餐饮,政府资源。逐渐的偏离我们一开始的合作的初衷。杜老板越来越感觉到不安和失控。这个时候,他们也开始频繁的私下接触我,并一再表达我可以单独和他们进行合作的意思,还开出了很大的待遇和承诺。那个时候,我确实处于左右为难的处境:困境还没走出,巨大的诱惑又摆在面前。是应该向现实屈服,还是捍卫看起来还很愚蠢的理想,我一次又一次徘徊在北大楼前面,一次又一次的拷问自己,评估每个决定的风险和利益,思考每条道路可能的结果。由于这个事情的性质特殊,我找不到可以倾诉的对象,找不到可以给我指导的前辈和朋友,这个决定很艰难,影响也很大,我必须自己来做。

 

最终,我站在北大楼前面,做了一个和一年前一样的决定,坚守了一年前曾经下的3年之约。我拒绝了梅的挖角,并希望保持正常的合作关系。虽然知道这对于他来说,这不太可能。他们是销售人员,思维方式和我们这些做产品的人是不一样的。他们是要不惜一切手段忽悠客户把项目拿到手,而不管产品如何交付,因此他们的很多想法都和我们背道而驰。道不同不相为谋,我跟加入他们的团队对我的个人能力发展和日后的发展不会有太多帮助。可能眼前的利益会比较可观,但难道我是为了钱而一个人留在南京奋斗吗?每次抚心自问,虽然都会有所动摇,但最终答案都是一样。这件事情可以看出来,我还是不够坚定,还是容易受别人影响;我有点过于善良了,在商场,盲目的善良只会招致对自己的伤害。并不是所有事情都能找到皆大欢喜的解决方案,不想伤害任何人,最终只会伤害所有人。正如世界是公平的,但却不在同一个点上体现,而是动态平衡,此消彼长。多赢的解决方法可与而不可求。

人生的旅途上,沿途会有很多引人入胜的风景,你可以去欣赏,游玩,小憩,也可以当作你心灵的圣地,在那里思考,忏悔,祷告。但千万不可留连忘返,乐不思蜀。每个人都有自己命中注定的目的地,如果你的目的地不在这里,尽管美景再美,也不属于你。不要挤破头去成为别人的风景,那样子你要么大煞风景,要么成为装饰物。与其浪费生命,不如尽早收拾心情赶路,用你生命最美好的时光去装饰属于你的风景,画一幅有你独特风格的美画。

 

第一个天使投资

 

接着,5月份的时候,我认识了老张,一个互联网的老鸟,网络营销高手。我们基于杜的关系,走到一起,合作开发一个网络营销工具。我在这个时候体验到做一个产品的兴奋和刺激。不久,我们就了解到学校联合苏福特在搞一个创业英才计划,挑选优秀的学生项目投资。这对我们来说就是一道绝境中的曙光。然而,希望之光还没有沐浴到,我们团队内部就出现了矛盾,自然是利益分成的问题。多数的创业团队都是死在美好的明天的前一个晚上,可以共患难,但不可以共富贵,哪怕是虚无缥缈的富贵。人在利益面前都变得很丑陋,这也是人的天性。互不相让,咄咄逼人,互相猜忌,勾心斗角。。。。。老张那时候就对我说,这事情能不能做成,就看你能不能把所有人的矛盾消除或者缓和,建立共同愿景和一致的利益关系。于是,我选择自我牺牲,站在道德的高度来解决了双方的矛盾。这对于大多数人来说都是愚蠢的决定,但是我的哲学就是以退为进,我知道我想要的不是眼前的利益,而是一个充实的过程加上一个也许并不完美的结果。我成为了团队leader,第一次编写项目计划书,第一次上台做项目presentation,第一次参加投资商谈判,第一次编写投资协议,第一次签署合作协议,第一次成为股东。虽然中途几经破折,方向改变了好几次,好几次都差点走到要前功尽弃的地步,但又一次又一次地遇到新的关键人物,带来了一线生机,然后又因为各方的利益关系矛盾一次有一次的谈判破裂。

 

最终在蔡总和刘总的强势坚持下,我们终于完成了这起小额投资。用蔡总的话说,我们现在最缺的不是钱,而是各种资源的整合和公司运营、管理的学习。苏福特在这方面还是可以给我们提供很大的帮助的,虽然有点相互利用的味道,但这也是游戏的规则。的确,就目前而言,我们团队也只能支配这个额度的资金,我们在公司战略思考,市场定位和产品研发方面存在太多的不足。创业不可以浮躁,任何企业都不是一蹴而就的。创业这条路注定是荆棘丛丛,我们需要在挫折中成长,广交朋友,勇往直前。

 

11月份,当我站在学校报告厅讲台上,接过潘总的那张大型道具支票,这个事情终于修成正果。接下来,如何找准我们自己的定位,如何整合苏福特的资源,如何作为一个管理者去运营一个小公司,都是我必须面对的工作,而且都是我不擅长的工作。真想说一句,尼玛的,这绝逼是一条不归路。

 

不过值得庆幸的是,一路走来,我从老张,蔡总他们身上学到了很多很多的东西——企业运营,市场销售,网络营销,战略规划,产品设计,团队管理。老张缜密的思维和强大的逻辑思考能力,蔡总敏锐的市场洞察力和老练的规划运营手段,都一次次地让我打开眼界,叹为观止。不经不觉的,我的思考方式,处事方式也有了很大的进步,终于不再是以往那个只会胡思乱想做白日梦的愤青。理性科学的思维能力,再加上雷厉风行的执行力,是把事情做好的两个必要能力。记得大学的刘老师跟我说过,“你们现在做事情,千万不要半途而废,否则对你们以后会产生很大的阴影。”到了社会上,才知道这句话的用意。在这个称之为社会的地方,有一个叫做现实的敌人,他会在你做事情的路上,给你创造太多的无可奈何和绝望。如果你没有一个叫坚持的朋友,你只会一次又一次地退缩和绕路,而且还是麻木地,垂头丧气地放弃。

 

博弈与取舍

 

我一直认为人生是公平的,等价交换是一条不可违反的自然法则。你要得到一个东西,你就得付出同等价值的东西。承受一分的痛苦,才能换来一分的快乐。想享受常人无法享受的快乐,也得承受常人无法承受的痛苦。选择了创业,就选择小公司,小平台,忙碌繁杂的工作,充满机遇与挑战的人生。选择了创业,很难有大公司的荣耀感,归属感,光鲜的工资和福利,没有那么多大牛大神在你指导你,给你学习,没有很规范的流程和规范。这些小公司没有的东西都需要靠自己的成长来一一创造,个中艰辛不言而喻。我既向往着拥有属于自己的一番事业,也向往着那些大公司的种种美好,虽然明白这是矛盾的,但人本身就是矛盾集合体。但羡慕的东西跟理想是不一样的,理想是需要用一辈子去捍卫的瑰宝,羡慕的东西只是这个过程中一些美好的风景,我们不能被美好的风景吸引而忘了人生道路的目标。而且,我之所以会羡慕那些东西,不是因为我心之所向,而是因为我从来没有得到过,这是嫉妒心理,人之常情。我们现在所生活的世界是一个物欲横流的社会,身边的诱惑实在太多了,很多人会迷失其中不能自拔。看清自己内心所向往的东西,抵抗诱惑是一件相当困难的事情,有的人要花3年,有的人甚至花了大半辈子。做出正确的选择,又或者是尝试去寻找正确的道路,必然是个博弈和取舍的过程。世界是公平的,没那么多两全其美的好事,鱼与熊掌注定不可兼得,我必须做出取舍,显然,这个答案已经有了。为了得到我所向往的理想,我必须承受创业的艰辛,不安定,复杂的人际关系等等,必须放弃那些我所喜欢的东西,荣誉感,归属感,优越感。同时,选择了创业,在外人看来就是不稳定,高风险,忙碌,导致我的生活也发生了很多变化,朋友越来越不理解,知己越来越少。

 

选择什么样的工作,其实就选择了什么样的生活方式,毕竟工作也是生命的一大部分。刚毕业的时候,我还以为可以把工作和生活分得清清楚楚,让这两个圈子完全不相交。一年后,我知道这是多么的幼稚和不实际。工作和生活一定要有机结合,才能达到好好工作,好好生活的目标,强行隔断只会适得其反。

 

矛盾与自我

 

我就是个贱人啊,老是自己作践自己,追求一些超出自己能力范围的所谓理想,一而再再而三的让自己超负荷工作,不断的超越自己的极限才能勉强达到自己的要求。我之前对别人说,我的过去都是一个不断上升不断超越的过程,从一个环境换到另外一个环境,确定超越的目标,然后模仿、学习、超越。然而,我的目的地到底在哪呢,我到底为什么而前进,这个问题从我大二开始到现在,我都不敢给自己一个十分明确的答复。但有一点我可以坚信的是,我只要坚持去寻找,终有一天会找到的。

 

回首这一年所经历的一切,我对自己能力的认识再进了一步。我在系统分析,学习适应,换位思考,计划统筹等能力上确实有一定的优势,然而在执行力、意志力和决策力上也表现出相当的劣势。既然选择了创业,那就必须明确自己在将来的创业团队中所担当的角色。不同的角色需要不同的能力,执行、创新、管理、运营、销售、战略、决策、统筹,缺一不可,可以有一人拥有多种能力,但绝对不能缺少任何一种能力。我并没有那些大牛大神一样出色的专业能力,也没有那些站在商界业界顶端的企业家那样的历练和眼光。前者需要一定的天赋,后者需要长时间的磨练,都不是一蹴而就的东西。执行力和决策统筹方面的能力是我目前急需的培养的能力,而这两种能力正好一个是我的劣势,一个是我的优势。扬长避短,就是我接下来要做的事情。

 

人生是充满矛盾的,创造矛盾,缓和矛盾,解决矛盾,我们人生也差不多一直在干这三个事情。既然选择了这条道路,就要有牺牲和放弃的觉悟。之前一个师兄告诉我,选择程序员的道路是孤独的。然而,现在看来,跟创业比起来,程序员根本算不上真正的孤独。创业的路上,或许你会有很多的合作伙伴,有很多客户,但那不是朋友,不是生死之交。寻找理念一致,可以信赖,可以合作的伙伴是一个永不完结的课题。

 

2011与2012

 

技术:2011年技术基本上没有提高,自从决定创业之后,就很少接触具体的编码,大部分时间都在思考解决方案和产品设计上,做个几个小东西,如酒店比价和验证码破解,也了解了一下python。对流行的技术,如nosql,html5,node.js等都只是观望状态,毕竟从实际出发,目前还没有应用场景。2012年计划要自己动手做一个html5的应用,熟练掌握javascript前端开发和交互式设计,并且真正掌握python,能够用于项目开发。要用一年的时间带领团队开发和完善网络营销一体化应用工具。

 

收入:2011年上缴中央就好几W,自己剩下的也不多了,而且也有点挥霍无度。虽然我一直认为男人应该更多的想着怎么开源,而不是节流,但那也是在合理消费的前提下。虽然开始有了资产性收入,但毕竟有投资性质而且不能马上套现,所以总的来说2011年收入并不算太理想。2012年要把资产性收入翻一番,而且到手的资金也要达到一年前的年薪水平才行,克服不合理的消费,不该请的就不请,该请的绝不吝啬。花钱也要花的开心,如果明知道花了钱也毫无价值,那就不如把钱用在更好的地方。

 

读书:2011年一共才读了3本书,技术书的《重构》一般般,还是《乔布斯传记》给力,给了我很多指引和灵感,它毫无疑问已经成为我人生第四本重要书籍,准备读第二次,并写读后感。在读书这方面自己实在太差了,知识积累太薄弱。2012要争取读4本书,其中技术1本,管理方面1本,开拓视野方面1本,其他1本。

摄影:2011年入手了85 1.8,小人像王还是很不错的,就是焦段有点蛋疼,风景拍的少了,更多是拍人和扫街,个人感觉85会疏远摄影师和被摄对象,因此我需要一个短距离定焦头——35 1.4。所以,2012年计划入手35 1.4 ,一改重口味的风格,向老孔学习小清新。

旅游:2011年除了去了一趟北京和黄山,基本上没怎么出游过,太忙了,不过一部分原因是自己不愿意一个人去旅行。适应别人的时间或者让别人适应自己的时间都真心不靠谱,最终只会导致哪都去不成。要对自己好一点,因为没有人会把你当做全世界。能找到志同道合的驴友自然好,即使一个人也要旅行,去开阔自己的视野,去放松绷紧的神经,去寻求那片属于自己的宁静。2012年计划要去一趟婺源和厦门,特别向往农村的宁静和淳朴,也向往大海的壮阔和清爽。

 

事业:2011年公司总算是活下来,接下来就要看能不能取得很大的发展,要不然就会成为尴尬的存在。2012年需要把团队扩大一倍,营业额翻一番,争取百万级投资。产品也需要继续升级,做一个真正能够为用户创造价值的产品。争取和更大的公司合作,登上一个比苏福特更大的平台。

 

感情:2011年还是打光棍,原因嘛,自己也清楚,主观客观因素都有,总体来说不利因素蛮大的,暂时想不出怎么克服。而且按照哥这幅德性还是比较难突破的,身边avaliable的少之又少,自己又不愿意凑合,该怎么滴怎么地吧。相比那遥不可及的爱情,我感觉我更应该更多的关爱那些在遥远的家乡关心我的家人,年老的父母,开始长进的大哥,还有时日不多的老奶奶。一年才回一次家,我觉得自己过于自私,为了自己的追求,而疏远了自己的家人。理想,确实不是一个可以轻松说出口的东西,为了它,人们需要克服多少困难,舍弃多少,牺牲多少,还真的只有自己清楚。为了补偿,2012年,我要带我爸妈到南京来一趟,投资哥哥的工作室,帮他走上轨道,这个也算是对在国外辛苦打工的姐姐的一个安慰。至于自己的个人问题,还是随缘吧,学会等待,勇敢的等下去。

 

能力:2011年最大的发现就是自己的学习模式和能力优势——knight of owner,在认知范围内对事物的本质和工作原理进行了解,将其投影到现实的学习和应用中,以达到快速学习和领悟的效果。针对这种模式,需要进行一些特殊的训练,因此2012年需要强化自己的知识面和思考深度,下象棋和定期写博客是个不错的训练,还有就是学会通过与别人的沟通来提高思考速度,准确把握对方意图以作出应对。此外,2011年的我更多是在防守,思想有点过于保守,对事物的分析总是偏向于悲观的批判,而不是积极的去解决。理性的思维会让自己少犯错误,少走弯路,但同时也有可能让自己害怕冒险,错失机会,到底如何权衡,这是2012年必须要思考的问题。

Final

转眼间奔三都奔一半了,看看自己这个状态,确实蛮loser的。值得欣慰的是,自己还在自己选择的路上摸索前进,自己对自我的认识也逐步完善,内心的承受能力也日渐增强。有时候,大胆的放开双手,并不意味着你会失去一切,而是给自己一个拥抱整个世界的机会,一个完全属于你的世界。

JSon数据的解析

 

最近一个项目要对艺龙,携程等酒店预订网站进行价格信息采集.因为这两个网站都不是省油的灯啊,多次提交ajax表单,参数编码,获取特定的城市和酒店代码等等手段,可谓过五关斩六将,总算是把数据采集回来,但是又面临一个难题:采集回来的信息是json格式的,那就涉及到json数据转换成java对象了

首先要了解json数据的格式

[{"CityType":"hotel","TabList":[{"TabId":"1","Name":"\u70ED\u95E8","NameEn":"Hot","CityList":[{"ProvinceId":null,"CityId":"0101","CityCode":"0101","CityNameCn":"\u5317\u4EAC","CityNameEn":"Beijing","CityThreeSign":"","CityType":"hotel","OldEnglishName":"peking"},{"ProvinceId":null,"CityId":"0201","CityCode":"0201","CityNameCn":"\u4E0A\u6D77","CityNameEn":"Shanghai","CityThreeSign":"","CityType":"hotel","OldEnglishName":""},{"ProvinceId":null,"CityId":"2001","CityCode":"2001","CityNameCn":"\u5E7F\u5DDE","CityNameEn":"Guangzhou","CityThreeSign":"","CityType":"hotel","OldEnglishName":"canton"}]}]}];

jsonViewer是个好东西,不过HTTPAnalysis直接就集成了jsonViewer,不过还是前者比较轻巧:

json和java之间的互换可以使用json-lib, 基本的使用可以看文档就行.网上也有一些集成的类,我建议直接看它的源代码,了解他是如何通过反射和使用临时对象解析json数据,并封装成java对象.

这个json数据时list的嵌套,如果要对整个json文件解析,需要使用如下方法,需要构造跟json数据对应的Tab.class 和City.class,而且字段名称必须一致(骆驼首字母小写),提供默认构造方法,这样就可以将json数据作为一个完整的对象,想怎么干都行了.

 

HashMap<String,Class> map = new HashMap<String,Class>();
map.put("tabList", Tab.class);
map.put("cityList", City.class);

	    /**
	     * 从一个JSON数组得到一个java对象集合,其中对象中包含有集合属性
	     * @param object
	     * @param clazz
	     * @param map 集合属性的类型 (key : 集合属性名, value : 集合属性类型class) eg: ("beansList" : Bean.class)
	     * @return
	     */
	    public static List getDTOList(String jsonString, Class clazz, Map map){
	        setDataFormat2JAVA();
	        JSONArray array = JSONArray.fromObject(jsonString);
	        List list = new ArrayList();
	        for(Iterator iter = array.iterator(); iter.hasNext();){
	            JSONObject jsonObject = (JSONObject)iter.next();
	            list.add(JSONObject.toBean(jsonObject, clazz, map));
	        }
	        return list;
	    }     

由于我的需求只是需要重json数据中获取特定的信息对象,如上面的cityList,像tabList等对象我没必要去构造和获取,而且在实际使用过程中我发现

json数据中变量如果不是首字母小写,是无法转换成java对象的.这个确实很坑爹!!!!!

 

于是乎,我就写了个直接读取和解析一个片段json数据的类,有了这个类,加上对象映射,基本上没什么解析不了

 

package com.engine.logic.component.loader.impl.json.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class JSonStrUtils {

	/**
	 * json 数据括号自动补全
	 * **/
	public static String autoComplete(String targetJson){
		LinkedList<Character> stack = new LinkedList<Character>();
		String returnStr ="";
		char[] charArray = targetJson.toCharArray();
		for(int i = 0;i<charArray.length;i++){
			if(charArray[i]=='['||charArray[i]=='{'){//入栈
				stack.addFirst(charArray[i]);
			}else if(charArray[i]==']'){
				//判断是否闭合
				char last = stack.peekFirst();
				if(last !='['){//不闭合,补 }
					returnStr+='}';
				}else//闭合
				{
					stack.pollFirst();
				}
			}else if(charArray[i]=='}'){
				//判断是否闭合
				char last = stack.peekFirst();
				if(last !='{'){//不闭合,补 }
					returnStr+=']';
				}else//闭合
				{
					stack.pollFirst();
				}
			}
			returnStr+=charArray[i];
		}
		for(char c:stack){
			System.out.println("left in stack:"+c);
		}
		return returnStr;
	}

	/***
	 * 用于处理json数据中出现变量名非首字母小写的情况,利用正则匹配变量,然后把首字母变成小写
	 * */
	public static String dealWithFirstChar(String jsonInput){
		String originalInput = jsonInput;
		StringBuilder inputStr = new StringBuilder(jsonInput);
		String regex = "\"(\\w+)\":";
		Pattern p = Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(inputStr);
		List<String> result=new ArrayList<String>();
		while(m.find()){
			String valueName = m.group(1);
			String newValueName = null;
			char[] words =valueName.toCharArray();
			if(Character.isUpperCase(words[0])){//首字母大写,不符合变量命名规范

				words[0] = Character.toLowerCase(words[0]);
				newValueName = new String(words);
//				System.out.println("orignal value:"+valueName+" new value :"+ newValueName);
//				String regexWord = "\""+valueName+"\":";
				String regx1 = "\""+valueName+"\":";
				String replace = "\""+newValueName+"\":";
				originalInput=originalInput.replaceAll(regx1, replace);
			}
			result.add(valueName);
			inputStr.delete(0, m.end(0));
			m=p.matcher(inputStr);
		}
		return originalInput;

	}

	/***
	 * 用户将unicode编码转换成汉字
	 * */
	public static String UnicodeToString(String str) {
        Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
        Matcher matcher = pattern.matcher(str);
        char ch;
        while (matcher.find()) {
            ch = (char) Integer.parseInt(matcher.group(2), 16);
            str = str.replace(matcher.group(1), ch + "");
        }
        return str;
    }

	/***
	 * 用户将汉字转换成unicode编码
	 * */
	public static String toUNICODE(String s)
    {
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<s.length();i++)
        {
            if(s.charAt(i)<=256)
            {
                sb.append("\\u00");
            }
            else
            {
                sb.append("\\u");
            }
            sb.append(Integer.toHexString(s.charAt(i)).toUpperCase());
        }
        return sb.toString();
    }

	/**
	 * 读取json文件,转换为字符串
	 * */
	public static String readJSonFile(String fileName){
		InputStream in = null;
		String jsonStr = "";
		try {
			in = JSonStrUtils.class.getResourceAsStream(fileName);
			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			String temp = reader.readLine();
			while(temp!=null){
				jsonStr+=temp;
				temp = reader.readLine();
			}
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("read json file failed :"+fileName);
		}
		return jsonStr;
	}

	/***
	 * 在指定的JSONObject 中寻找特定属性的第一个值
	 * */
	public static List<String> findTargetProperty(JSONObject object,String propertyName,boolean isRecursive){
		List<String> values = new ArrayList<String>();
		for( Iterator entries = object.names().iterator();
		 entries.hasNext(); ){
			String name = (String) entries.next();
			Object value = object.get(name);
			if(name.equals(propertyName)){//找到目标属性
				values.add(value.toString());
			}else if(isRecursive){
				if(value instanceof JSONObject){
					values.addAll(findTargetProperty((JSONObject)value,propertyName,isRecursive));
				}else if(value instanceof JSONArray){
					JSONArray array = (JSONArray)value;
					for(Iterator iter = array.iterator(); iter.hasNext();){
						JSONObject jsonObject = (JSONObject)iter.next();
						values.addAll(findTargetProperty(jsonObject,propertyName,isRecursive));
					}
				}
			}
		}
		return values;
	}

	/***
	 * 从指定的JSonArray中寻找指定名称的子json数组
	 * */
    public  static List<JSONArray> findTargetJSonArray(JSONArray array,String targetName){
    	List<JSONArray> arrays = new ArrayList<JSONArray>();
    	for(Iterator iter = array.iterator(); iter.hasNext();){//遍历数组中的JSONObject
			JSONObject jsonObject = (JSONObject)iter.next();
			if( jsonObject == null || jsonObject.isNullObject() ){
		         continue;
		    }
			for( Iterator entries = jsonObject.names().iterator();
			 entries.hasNext(); ){
				 String name = (String) entries.next();
				 Object value = jsonObject.get(name);
				 if(value instanceof JSONArray){//属性为数组
					 //先判断是否目标数组
					 if(name.equals(targetName)){
						 arrays.add((JSONArray) value);
					 }
					 //递归查找
					 arrays.addAll(findTargetJSonArray((JSONArray) value,targetName));
				 }
			}
    	}
    	return arrays;

    }
}

java编程中’为了性能’一些尽量做到的地方

原文:http://www.blogjava.net/dongbule/archive/2011/08/15/356577.html

BlogJava-首页技术区 作者:陈于喆

有 7 人喜欢此条目

最近的机器内存又爆满了,出了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了。

下面是参考网络资源和总结一些在java编程中尽可能做到的一些地方
-

1.尽量在合适的场合使用单例

使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面

第一,控制资源的使用,通过线程同步来控制资源的并发访问

第二,控制实例的产生,以达到节约资源的目的

第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信
-
2.尽量避免随意使用静态变量

要知道,当某个对象被定义为stataic变量所引用,那么gc通常是不会回收这个对象所占有的内存,如

public class A{

static B b = new B();

}

此时静态变量b的生命周期与A类同步,如果A类不会卸载,那么b对象会常驻内存,直到程序终止。
-

3.尽量避免过多过常的创建java对象

尽量避免在经常调用的方法,循环中new对象,由于系统不仅要花费时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,在我们可以控制的范围内,最

大限度的重用对象,最好能用基本的数据类型或数组来替代对象。

-

4.尽量使用final修饰符

带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。

-

5.尽量使用局部变量

调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量,实例变量等,都在堆(Heap)中创建,速度较慢。
-

6.尽量处理好包装类型和基本类型两者的使用场所

虽然包装类型和基本类型在使用过程中是可以相互转换,但它们两者所产生的内存区域是完全不同的,基本类型数据产生和处理都在栈中处理,包装类型是对象,是在堆中产生实例。

在集合类对象,有对象方面需要的处理适用包装类型,其他的处理提倡使用基本类型。
-

7.慎用synchronized,尽量减小synchronize的方法

都知道,实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。synchronize方法被调用时,直接会把当前对象锁了,在方法执行完之前其他线程无法调用当前对象的其他方法。所以synchronize的方法尽量小,并且应尽量使用方法同步代替代码块同步。
-

8.尽量使用StringBuilder和StringBuffer进行字符串连接

这个就不多讲了
-

9.尽量不要使用finalize方法

实际上,将资源清理放在finalize方法中完成是非常不好的选择,由于GC的工作量很大,尤其是回收Young代内存时,大都会引起应用程序暂停,所以再选择使用finalize方法进行资源清理,会导致GC负担更大,程序运行效率更差。

-

10.尽量使用基本数据类型代替对象

String str = "hello";

上面这种方式会创建一个“hello”字符串,而且JVM的字符缓存池还会缓存这个字符串;

String str = new String("hello");

此时程序除创建字符串外,str所引用的String对象底层还包含一个char[]数组,这个char[]数组依次存放了h,e,l,l,o

-

11.单线程应尽量使用HashMap, ArrayList

HashTable,Vector等使用了同步机制,降低了性能。

-

12.尽量合理的创建HashMap

当你要创建一个比较大的hashMap时,充分利用另一个构造函数

public HashMap(int initialCapacity, float loadFactor)

避免HashMap多次进行了hash重构,扩容是一件很耗费性能的事,在默认中initialCapacity只有16,而loadFactor是0.75,需要多大的容量,你最好能准确的估计你所需要的最佳大小,同样的Hashtable,Vectors也是一样的道理。

-

13.尽量减少对变量的重复计算

for(int i=0;i<list.size();i++)

应该改为

for(int i=0,len=list.size();i<len;i++)

并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。

-

14.尽量避免不必要的创建

A a = new A();

if(i==1){list.add(a);}

应该改为

if(i==1){

A a = new A();

list.add(a);}

-

15.尽量在finally块中释放资源

程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。

-

16.尽量使用移位来代替’a/b’的操作

"/"是一个代价很高的操作,使用移位的操作将会更快和更有效

int num = a / 4;

int num = a / 8;

应该改为

int num = a >> 2;

int num = a >> 3;

但注意的是使用移位应添加注释,因为移位操作不直观,比较难理解

-

17.尽量使用移位来代替’a*b’的操作

同样的,对于’*'操作,使用移位的操作将会更快和更有效

int num = a * 4;

int num = a * 8;

应该改为

int num = a << 2;

int num = a << 3;

-

18.尽量确定StringBuffer的容量

StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。

如:StringBuffer buffer = new StringBuffer(1000); 

-

19.尽量早释放无用对象的引用

大部分时,方法局部引用变量所引用的对象 会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。

例如:

Public void test(){

Object obj = new Object();

……

Obj=null;

}

上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面:

Public void test(){

Object obj = new Object();

……

Obj=null;

//执行耗时,耗内存操作;或调用耗时,耗内存的方法

……

}

这时候就有必要将obj赋值为null,可以尽早的释放对Object对象的引用。

-

20.尽量避免使用二维数组

二维数据占用的内存空间比一维数组多得多,大概10倍以上。

-

21.尽量避免使用split

除非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。

-

22.ArrayList & LinkedList

一个是线性表,一个是链表,一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指针,添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据,不过这是理论性分析,事实未必如此,重要的是理解好2者得数据结构,对症下药。

-

23.尽量使用System.arraycopy ()代替通过来循环复制数组

System.arraycopy() 要比通过循环来复制数组快的多

-

24.尽量缓存经常使用的对象

尽可能将经常使用的对象进行缓存,可以使用数组,或HashMap的容器来进行缓存,但这种方式可能导致系统占用过多的缓存,性能下降,推荐可以使用一些第三方的开源工具,如EhCache,Oscache进行缓存,他们基本都实现了FIFO/FLU等缓存算法。

-

25.尽量避免非常大的内存分配

有时候问题不是由当时的堆状态造成的,而是因为分配失败造成的。分配的内存块都必须是连续的,而随着堆越来越满,找到较大的连续块越来越困难。

-

26.慎用异常

当创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。当需要创建一个 Exception 时,JVM 不得不说:先别动,我想就您现在的样子存一份快照,所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素,而是包含这个栈中的每一个元素。

如果您创建一个 Exception ,就得付出代价。好在捕获异常开销不大,因此可以使用 try-catch 将核心内容包起来。从技术上讲,您甚至可以随意地抛出异常,而不用花费很大的代价。招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常。幸运的是,好的编程习惯已教会我们,不应该不管三七二十一就抛出异常。异常是为异常的情况而设计的,使用时也应该牢记这一原则。
文章主要是为了抛砖引玉,希望有更多牛人的指点
谢谢的 

xuanyuan 的建议:
===================================================
7.慎用synchronized,尽量减小synchronize的方法
re:同意,不过文中有个地方说错了,使用synchronized关键字并不一定都是锁定当前对象的,要看具体的锁是什么。如果是在方法上加的synchronized,则是以对象本身为锁的,如果是静态方法则锁的粒度是类。
—————
9.尽量不要使用finalize方法
re:同意,其实不推荐用finalize方法的根本原因在于,JVM的规范并不保证何时执行该方法,所以用这个方法来释放资源很不合适,有可能造成长时间资源得不到释放。
—————
16.尽量使用移位来代替’a/b’的操作;17.尽量使用移位来代替’a*b’的操作
re:个人不太同意这两条。这样做确实有更好的性能,但是却牺牲了可读性。这两个操作符对很多程序员来说并不直观。我认为在如今硬件价格不那么昂贵的情况下,略微牺牲一些性能,换来更好的可读性和可维护性是好的选择。
===================================================

转:Java 开发 2.0: 面向 Java 开发人员的 JavaScript

对于早期的 Java 平台,新闻记者,甚至新手程序员经常会将 JavaScript 与 Java 语言搞混。这两种语言之所以普及,是因为它们都适合于 Web 编程,而且它们也经常同时出现在大众面前。今天,大多数人都能区分这两种语言,但 Java 开发人员仍然普遍不看好 JavaScript,甚至觉得它不适用于脚本中。但现实情况是,JavaScript(很像 Java 语言)不但存在,甚至还在不断演进。它是 Ajax 这类客户端编程技术与 Node.js 这类服务器端编程技术的基础,它对于移动应用程序开发的出现也很重要。它也支持在非常流行的 Google Web Toolkit(或 GWT)中编译 Java 代码。

Java 开发 2.0: 面向 Java 开发人员的 JavaScript

定向采集搜索引擎文章收藏

定向抓取漫谈  长孙泰

原文:http://www.searchtb.com/2011/01/an-introduction-to-crawler.html

网络爬虫(web crawler)又称为网络蜘蛛(web spider)是一段计算机程序,它从互联网上按照一定的逻辑和算法抓取和下载互联网的网页,是搜索引擎的一个重要组成部分。一般的爬虫从一部分start url开始,按照一定的策略开始爬取,爬取到的新的url在放入到爬取队列之中,然后进行新一轮的爬取,直到抓取完毕为止。

我们看一下crawler一般会遇到什么样的问题吧:

  1. 抓取的网页量很大
  2. 网页更新量也很大,一般的网站,比如新闻,电子商务网站,页面基本是实时更新的
  3. 大部分的网页都是动态的,多媒体,或者封闭的(facebook)

海量网页的存在就意味着在一定时间之内,抓取只能的抓取其中的一部分,因此需要定义清楚抓取的优先级;网页更新的频繁,也就意味着需要抓取最新的网页和保证链接的有效性,因此一个更有可能带来新网页的列表页显得尤为重要;对于新闻网站,新的网站一般出现在首页,或者在指定的分类网页,但是对于淘宝来说,商品的更新就很难估计了;动态网页怎么办呢?现在的网页大都有JS和AJAX,抓取已经不是简单的执行wget下载,现代的网页结构需要我们的爬虫更加智能,需要更灵活的应对网页的各种情况。

因此,对一个通用的爬虫个,我们要定义

  1. 抓取策略,那些网页是我们需要去下载的,那些是无需下载的,那些网页是我们优先下载的,定义清楚之后,能节省很多无谓的爬取
  2. 更新策略,监控列表页来发现新的页面;定期check页面是否过期等等
  3. 抽取策略,我们应该如何的从网页中抽取我们想要的内容,不仅仅包含最终的目标内容,还有下一步要抓取的url
  4. 抓取频率,我们需要合理的去下载一个网站,却又不失效率

抓取策略

使用URL的正则特征是一个简单但却很高效的模式;对于定向抓取,一般的网站的URL有一定的特征,比如可能仅仅关心 .html, .htm, .asp, .aspx, .php, .jsp, .jspx类型的网页;或者是如果可以得到目标网站的正则,则可以大大的降低抓取的数量;又或者我们无需关心某一类网页,比如我们不抓取bbs.taobao.com下面的内容;仅仅需要抓取淘宝的商品页面(http://item.taobao.com/item.htm?id=\d+ )。通过URL的正则能极大的降低抓取数量;

也可以通过网页的文本特征来确定;不过要复杂得多了,一般需要一定数量已知页面的训练集合,然后提取页面的文本特征,然后通过向量空间模型或者其其他基于主题词提取的模型计算目标网页和训练集网页的距离,决定是否是目标网页。

更新策略

Freshness:表示抓取到的网页是否已经被修改

Age:表示抓取的网页过期的时间

对于更新来说,目标是让平均age时间越小,freshness越高;一般的更新策略有两种:定期批量更新和按更新周期更新;定期批量更新指对一批URL,按照失效时间定期去刷新,按周期更新指的是按照页面更新变化频率而修正是更新频率,一般来说,更新越频繁的网页更新也就越快。

抽取策略:

XPATH是一个简单直观,但是很有效的一个方案,XPATH能精准的定位网页的任意一个位置,意味着我们可以很精准的抽取页面上的任意位置,当面临很多网站的时候,当然配置XPATH就是一个很艰巨的任务,也许存在一个自适应的XPATH识别的方法。

JS和AJAX

在java下面,HtmlUnit是一个不错的解决方案,HtmlUnit是Junit 的扩展测试框架之一,该框架模拟浏览器的行为,开发者可以使用其提供的API对页面的元素进行操作,套用官方网站的话HtmlUnit“是Java程序的浏览器”。HtmlUnit支持HTTP,HTTPS,COOKIE,表单的POST和GET方法,能够对HTML文档进行包装,页面的各种元素都可以被当作对象进行调用,另外对JavaScript的支持也比较好。一般来说,HtmlUnit是在java环境下解决JS的很好的选择

WebKit包含一个网页引擎WebCore和一个脚本引擎JavaScriptCore,它们分别对应的是KDE的KHTMLKJS;目前比较主流的浏览器Google Chrome和Apple的safari,都是基于WebKit的内核写的。使用浏览器作为抓取能更好的模拟用户浏览的行为,能够天然的解决JS和AJAX等问题,问题可能就是性能是一个瓶颈,

抓取频率

同时开启N个线程抓取一个网站,相信很快就会被对方网站封掉;因此抓取的频率也很重要;抓取网站同时不对对方网站造成压力;在robot.txt协议里面定义Crawl-delay来确定抓取的频率也是一种网站的通用的做法,对于一般的抓取而言,10到20秒抓取一次是一个比较保险的频率,也有提出10*t的抓取间隔(t是download时间)比较合理

定向抓取的框架

通用抓取架构,如下图

多线程下载模块(Multi-threaded downloader)

该模块一般包含:

  1. 下载模块,下载网页,并应对一些web的一些错误,包括redirect等等
  2. DNS解析模块,网页数量很多的时候,我们需要一个本地的DNS解析模块来维护domain到IP的映射
  3. 链接抽取模块,抽取下一步要抓取的链接(follow link)

调度模块(schedule)

调度模块是抓取系统的核心,调度模块从url队列里面选择一批url喂到下载模块下载;其中会涉及到

  1. url调度,调度模块按照一定的策略,选取url进入抓取系统
  2. url除重,一定时期之内已经抓取的网页,不再抓取

java 多线程程序调试

 

可能java多线程是一个应用非常广泛的技术,特别是jkd5.0 concurrent包出现后,线程池等应用门槛越来越低,导致多线程程序泛滥.但是,如果多线程应用不当,对于是很多java程序员的多线程是一个噩梦,因为调试困难而且问题诡异.

通常多线程程序调试采取的方法有

1.添加关键打印信息

2.监控线程运行情况

第一个方法比较笨,但不失为最有效的方法,方法2就必须依赖一些工具,譬如说jdk自家的visualVM(jdk bin目录下visulvm.,exe)

多线程程序经常会出现内存溢出,莫名其妙的终止等问题,解决这些问题必须结合以上两个方法,

先用visulvm把出现问题的程序线程快照dump下来,就是著名的Thread dump,然后查看每个线程的状态和运行堆栈信息,如果线程出现死锁或者错误的等待,可以看到具体等待的代码.然后通过添加打印信息最终确定问题所在.

 

关于visualvm的用法参见:http://www.longtask.com/blog/?p=465

SimpleDateFormat解析英文日期

之前一直以为SimpleDateFormat就是两个方法,parse和format,一个把字符串解析成日期,一个把日期格式化为字符串,却不知道原来还有很多细枝末节.昨天就遇到一个解析英文日期的问题,我要解析的日期格式是:

Wed Mar 31 15:13:53 +0800 2010,然后我按照jdk api文档的要求,写了这样的格式字符串:

EEE MMM dd HH:mm:ss Z yyyy

String time = "Wed Mar 31 15:13:53 +0800 2010";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
try{
	System.out.println(df.format(sdf.parse(time)));
} catch (ParseException e)
{
	System.out.println("time 格式错误");
}
		

看起来完全正确,但是就是解析错误,搜了半天google,都确定格式字符串是没有错误的,结果在一篇文章里面发现日期解析SimpleDateFormat的构造方法还可以带一个参数,Locale locale语言环境,如果不设置正确的语言环境是无法使用SimpleDateFormat去解析日期的,因为web,mar这样的英文格式属于美国语言环境,所以要添加locale才行

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US);
try{
	System.out.println(df.format(sdf.parse(time)));
} catch (ParseException e)
{
	System.out.println("time 格式错误");
}
		

监控线程的运行情况

开发过程中我们经常会用到线程池,虽然方便,但是有的时候我们需要了解每个线程的运行情况,譬如线程处于什么状态,执行到哪一行代码.

线程池我们一般都会使用java.concurrent包里面的ThreadPoolExecutor,他的其中一个构造方法是带ThreadFactory参数的,通过自定义ThreadFactory我们可以自定义线程的名称和优先级等

 

package com.engine.logic.component.loader.executor;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class MyThreadFactory implements ThreadFactory{

	private String _name;
	private AtomicInteger _threadNumber = new AtomicInteger(1);
	private ThreadGroup _group;

	 public MyThreadFactory(String name)
	  {
	      _name = name;
	      _group = new ThreadGroup(_name);
	  }

	  public Thread newThread(Runnable r)
	  {
	        Thread t = new Thread(_group, r);
	        t.setName(_name + "-" + _threadNumber.getAndIncrement());
	        return t;
	  }

	  public ThreadGroup getGroup()
	  {
	        return _group;
	  }

	  public String printThreadStatus(){
		  StringBuilder sb = new StringBuilder();
		int threadCount = _threadNumber.intValue();
        sb.append("thread count :"+threadCount+"\r\n");
		Thread[] threads = new Thread[threadCount+2];
 	    _group.enumerate(threads);
 	   for (Thread t : threads)
       {
           if (t == null)
               continue;
           sb.append(t.getName()+" thread stacktrace:========================\r\n");
           for (StackTraceElement ste : t.getStackTrace())
           {
        	   sb.append(ste.toString()+"\r\n");
           }
       }
 	   return sb.toString();
	  }

}

关于接口ThreadFactory可以看API文档,只有一个方法newThread,此工厂的目的是让这个池里的线程归并到默认的线程组里并且拥有相同的优先级等。上面的类主要目的是方便日志记录。怎么记录呢,

主要是通过里面的ThreadGroup获取所有线程,然后打印StackTraceElement的信息,如下

 

sun.misc.Unsafe.park(Native Method)

java.util.concurrent.locks.LockSupport.park(Unknown Source)

java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)

java.util.concurrent.PriorityBlockingQueue.take(Unknown Source)

java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)

java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)