淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和

Posted on

淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和 - Java综合 - Java - JavaEye论坛

您还未登录 ! 我的应用 登录 注册

JavaEye-最棒的软件开发交流社区

论坛首页Java编程和Java企业应用版Java综合

淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和

全部 Hibernate Spring Struts iBATIS 企业应用 设计模式 DAO 领域模型 OO Tomcat SOA JBoss Swing Java综合

myApps快速开发平台,配置即开发、所见即所得,节约85%工作量

« 上一页 1 2 315 16 下一页 » 浏览 24475 次 主题:淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和

该帖已经被评为良好帖 作者 正文 * 飞雪无情

  • 等级: 一星会员
  • 飞雪无情的博客
  • 文章: 50
  • 积分: 110
  • 来自: 河南
  • 发表时间:2010-07-12 最后修改:2010-07-14

< > 猎头职位:

相关文章:

前几天在网上看到一个淘宝的面试题:有一个很大的整数list,需要求这个list中所有整数的和,写一个可以充分利用多核CPU的代码,来计算结果。 一:分析题目 从题中可以看到“很大的List”以及“充分利用多核CPU”,这就已经充分告诉我们要采用多线程(任务)进行编写。具体怎么做呢?大概的思路就是分割List,每一小块的List采用一个线程(任务)进行计算其和,最后等待所有的线程(任务)都执行完后就可得到这个“很大的List”中所有整数的和。 二:具体分析和技术方案 既然我们已经决定采用多线程(任务),并且还要分割List,每一小块的List采用一个线程(任务)进行计算其和,那么我们必须要等待所有的线程(任务)完成之后才能得到正确的结果,那么怎么才能保证“等待所有的线程(任务)完成之后输出结果呢”?这就要靠java.util.concurrent包中的CyclicBarrier类了。它是一个同步辅助类,它允许一组线程(任务)互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程(任务)的程序中,这些线程(任务)必须不时地互相等待,此时 CyclicBarrier 很有用。简单的概括其适应场景就是:当一组线程(任务)并发的执行一件工作的时候,必须等待所有的线程(任务)都完成时才能进行下一个步骤。具体技术方案步骤如下:

  • 分割List,根据采用的线程(任务)数平均分配,即list.size()/threadCounts。
  • 定义一个记录“很大List”中所有整数和的变量sum,采用一个线程(任务)处理一个分割后的子List,计算子List中所有整数和(subSum),然后把和(subSum)累加到sum上。
  • 等待所有线程(任务)完成后输出总和(sum)的值。 示意图如下: 三:详细编码实现 代码中有很详细的注释,这里就不解释了。 /// / 计算List中所有整数的和
    /
    采用多线程,分割List计算 / @author 飞雪无情 / @since 2010-7-12 // public class CountListIntegerSum { private long sum;//存放整数的和 private CyclicBarrier barrier;//障栅集合点(同步器) private List list;//整数集合List private int threadCounts;//使用的线程数 public CountListIntegerSum(List list,int threadCounts) { this.list=list; this.threadCounts=threadCounts; } /// / 获取List中所有整数的和 / @return // public long getIntegerSum(){ ExecutorService exec=Executors.newFixedThreadPool(threadCounts); int len=list.size()/threadCounts;//平均分割List //List中的数量没有线程数多(很少存在) if(len==0){ threadCounts=list.size();//采用一个线程处理List中的一个元素 len=list.size()/threadCounts;//重新平均分割List } barrier=new CyclicBarrier(threadCounts+1); for(int i=0;ilist.size()?list.size():len/(i+1)))); } } try { barrier.await();//关键,使该线程在障栅处等待,直到所有的线程都到达障栅处 } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName()+":Interrupted"); } catch (BrokenBarrierException e) { System.out.println(Thread.currentThread().getName()+":BrokenBarrier"); } exec.shutdown(); return sum; } /// / 分割计算List整数和的线程任务 / @author lishuai / // public class SubIntegerSumTask implements Runnable{ private List subList; public SubIntegerSumTask(List subList) { this.subList=subList; } public void run() { long subSum=0L; for (Integer i : subList) { subSum += i; } synchronized(CountListIntegerSum.this){//在CountListIntegerSum对象上同步 sum+=subSum; } try { barrier.await();//关键,使该线程在障栅处等待,直到所有的线程都到达障栅处 } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName()+":Interrupted"); } catch (BrokenBarrierException e) { System.out.println(Thread.currentThread().getName()+":BrokenBarrier"); } System.out.println("分配给线程:"+Thread.currentThread().getName()+"那一部分List的整数和为:\tSubSum:"+subSum); } } } 有人可能对barrier=new CyclicBarrier(threadCounts+1);//创建的线程数和主线程main有点不解,不是采用的线程(任务)数是threadCounts个吗?怎么为CyclicBarrier设置的给定数量的线程参与者比我们要采用的线程数多一个呢?答案就是这个多出来的一个用于控制main主线程的,主线程也要等待,它要等待其他所有的线程完成才能输出sum值,这样才能保证sum值的正确性,如果main不等待的话,那么结果将是不可预料的。 /// / 计算List中所有整数的和测试类 / @author 飞雪无情 / @since 2010-7-12 // public class CountListIntegerSumMain { /// / @param args // public static void main(String[] args) { List list = new ArrayList(); int threadCounts = 10;//采用的线程数 //生成的List数据 for (int i = 1; i <= 1000000; i++) { list.add(i); } CountListIntegerSum countListIntegerSum=new CountListIntegerSum(list,threadCounts); long sum=countListIntegerSum.getIntegerSum(); System.out.println("List中所有整数的和为:"+sum); } } 四:总结 本文主要通过一个淘宝的面试题为引子,介绍了并发的一点小知识,主要是介绍通过CyclicBarrier同步辅助器辅助多个并发任务共同完成一件工作。Java SE5的java.util.concurrent引入了大量的设计来解决并发问题,使用它们有助于我们编写更加简单而健壮的并发程序。 附mathfox提到的ExecutorService.invokeAll()方法的实现 这个不用自己控制等待,invokeAll执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。sdh5724也说用了同步,性能不好。这个去掉了同步,根据返回结果的 Future 列表相加就得到总和了。/// / 使用ExecutorService的invokeAll方法计算 / @author 飞雪无情 / // public class CountSumWithCallable { /// / @param args / @throws InterruptedException / @throws ExecutionException // public static void main(String[] args) throws InterruptedException, ExecutionException { int threadCounts =19;//使用的线程数 long sum=0; ExecutorService exec=Executors.newFixedThreadPool(threadCounts); List> callList=new ArrayList>(); //生成很大的List List list = new ArrayList(); for (int i = 0; i <= 1000000; i++) { list.add(i); } int len=list.size()/threadCounts;//平均分割List //List中的数量没有线程数多(很少存在) if(len==0){ threadCounts=list.size();//采用一个线程处理List中的一个元素 len=list.size()/threadCounts;//重新平均分割List } for(int i=0;i subList; if(i==threadCounts-1){ subList=list.subList(i/len,list.size()); }else{ subList=list.subList(i/len, len/(i+1)>list.size()?list.size():len/(i+1)); } //采用匿名内部类实现 callList.add(new Callable(){ public Long call() throws Exception { long subSum=0L; for(Integer i:subList){ subSum+=i; } System.out.println("分配给线程:"+Thread.currentThread().getName()+"那一部分List的整数和为:\tSubSum:"+subSum); return subSum; } }); } List> futureList=exec.invokeAll(callList); for(Future future:futureList){ sum+=future.get(); } exec.shutdown(); System.out.println(sum); } } 一些感言 这篇文章是昨天夜里11点多写好的,我当时是在网上看到了这个题目,就做了一下分析,写了实现代码,由于水平有限,难免有bug,这里感谢xifo等人的指正。这些帖子从发表到现在不到24小时的时间里创造了近9000的浏览次数,回复近100,这是我没有想到的,javaeye很久没这么疯狂过啦。这不是因为我的算法多好,而是因为这个题目、这篇帖子所体现出的意义。大家在看完这篇帖子后不光指正错误,还对方案进行了改进,关键是思考,人的思维是无穷的,只要我们善于发掘,善于思考,总能想出一些意想不到的方案。 从算法看,或者从题目场景对比代码实现来看,或许不是一篇很好的帖子,但是我说这篇帖子是很有意义的,方案也是在很多场景适用,有时我们可以假设这不是计算和,而是把数据写到一个个的小文件里,或者是分割进行网络传输等等,都有一定的启发,特别是回帖中的讨论。 单说一下回帖,我建议进来的人尽量看完所有的回帖,因为这里是很多人集思广益的精华,这里有他们分析问题,解决问题的思路,还有每个人提到的解决方案,想想为什么能用?为什么不能用?为什么好?为什么不好? *我一直相信:讨论是解决问题、提高水平的最佳方式!
  • 大小: 95.8 KB

  • 查看图片附件

声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。 推荐链接

  • adobe 返回顶楼 * coffeefeel
  • 等级: 初级会员
  • coffeefeel的博客
  • 文章: 1
  • 积分: 30
  • 来自: 北京
  • 发表时间:2010-07-13

飞雪无情 写道

synchronized(CountListIntegerSum.this){//在CountListIntegerSum对象上同步 sum+=subSum; } 实际效果还是顺序累加的? 返回顶楼 回帖地址

0 0 请登录后投票 * 飞雪无情

  • 等级: 一星会员
  • 飞雪无情的博客
  • 文章: 50
  • 积分: 110
  • 来自: 河南
  • 发表时间:2010-07-13

coffeefeel 写道

飞雪无情 写道

synchronized(CountListIntegerSum.this){//在CountListIntegerSum对象上同步 sum+=subSum; } 实际效果还是顺序累加的? 这个List不管分多少段,最终总要合并到一起。因为这个累加是每个线程(任务)执行的,所以累加不是顺序的,哪个线程(任务)先完成计算分割List部分的和,哪个线程(任务)就先进行累加。 返回顶楼 回帖地址

0 0 请登录后投票 * p2bl

  • 等级: 初级会员
  • p2bl的博客
  • 文章: 19
  • 积分: 40
  • 来自: 南京
  • 发表时间:2010-07-13

有点一个jvm里的mapreduce的意思 返回顶楼 回帖地址

1 0 请登录后投票 * 飞雪无情

  • 等级: 一星会员
  • 飞雪无情的博客
  • 文章: 50
  • 积分: 110
  • 来自: 河南
  • 发表时间:2010-07-13

p2bl 写道

有点一个jvm里的mapreduce的意思 呵呵。。这个和那个差的远,即使有点那么个意思也是冰山一角。呵呵。 返回顶楼 回帖地址

0 0 请登录后投票 * hrsvici412

  • 等级: 初级会员
  • hrsvici412的博客
  • 文章: 32
  • 积分: 30
  • 来自: 上海
  • 发表时间:2010-07-13

学到好多线程的东西,请问 你的分析的图,是用什么工具画的! 返回顶楼 回帖地址

0 0 请登录后投票 * mathfox

  • 等级: 初级会员
  • mathfox的博客
  • 文章: 208
  • 积分: 40
  • 来自: 北京
  • 发表时间:2010-07-13

引用

本文主要通过一个淘宝的面试题为引子,介绍了并发的一点小知识,主要是介绍通过CyclicBarrier同步辅助器辅助多个并发任务共同完成一件工作。Java SE5的java.util.concurrent引入了大量的设计来解决并发问题,使用它们有助于我们编写更加简单而健壮的并发程序。 不用这么麻烦吧 用ExecutorService.invokeAll就行了吧。 返回顶楼 回帖地址

1 0 请登录后投票 * numen_wlm

  • 等级: 初级会员
  • numen_wlm的博客
  • 文章: 48
  • 积分: 12
  • 来自: 上海
  • 发表时间:2010-07-13

有时间研究下CyclicBarrier里面是怎么处理的。 返回顶楼 回帖地址

0 0 请登录后投票 * xifo

  • 等级: 初级会员
  • xifo的博客
  • 文章: 20
  • 积分: 43
  • 来自: 安徽
  • 发表时间:2010-07-13 最后修改:2010-07-13

思路是对的,可惜算法有问题,大多数情况下计算结果不正确。 不信的话,试试把这一行 for (int i = 1; i <= 1000000; i++) 换成 for (int i = 0; i <= 1000000; i++) 如果计算正确,两个计算结果应该一样,实际上计算结果会少一百万,原因是分割那里没有考虑尾数。 返回顶楼 回帖地址

1 0 请登录后投票 * 飞雪无情

  • 等级: 一星会员
  • 飞雪无情的博客
  • 文章: 50
  • 积分: 110
  • 来自: 河南
  • 发表时间:2010-07-13

hrsvici412 写道

学到好多线程的东西,请问 你的分析的图,是用什么工具画的! 用的是Edraw 返回顶楼 回帖地址

0 0 请登录后投票

« 上一页 1 2 315 16 下一页 » 论坛首页Java编程和Java企业应用版Java综合 跳转论坛:Java编程和Java企业应用 Web前端技术 移动编程和手机应用开发 C/C++编程 Ruby编程 Python编程 PHP编程 Flash编程和RIA Microsoft .Net 综合技术 软件开发和项目管理 行业应用 入门讨论 招聘求职 海阔天空

© 2003-2010 JavaEye.com. 上海炯耐计算机软件有限公司版权所有 [ 沪ICP备05023328号 ]

我在Oracle和IBM的面试经历

Posted on

我在Oracle和IBM的面试经历

您还未登录 ! 我的应用 登录 注册

JavaEye-最棒的软件开发交流社区

论坛首页招聘求职版职场话题

我在Oracle和IBM的面试经历

全部 企业点评 职场话题 求职经验 面试秘籍 招聘职位

myApps快速开发平台,配置即开发、所见即所得,节约85%工作量

« 上一页 1 2 3 下一页 » 浏览 5251 次 主题:我在Oracle和IBM的面试经历

精华帖 (0) :: 良好帖 (0) :: 隐藏帖 (0) 作者 正文 * yangstarfly

  • 等级: 四星会员
  • yangstarfly的博客
  • 文章: 88
  • 积分: 417
  • 来自: 北京
  • 发表时间:昨天

< > 猎头职位:

相关文章:

  • Google 面试归来:
  • 深圳oracle 怎么样?有谁了解这个公司的吗?
  • 迪易通,等你等到我心痛 推荐圈子: 中国外派技术人员联盟 更多相关推荐 我是Javaeye的老会员了,好久没来发帖了。最近正好找工作,想和大家分享一下。在我面试过的公司中,最有名的是IBM, Oracle, 百度。目前已经拿到IBM CSTL, Oracle北京研发中心的Offer。到底去哪家我还没想好。 IBM的面试经历比较简单。只有2轮面试。每轮都是技术+英语。一个月后通知我拿到Offer. Oracle三轮面试+一轮电面,除了电面外,每轮都有英语对话。也差不多是一个月后给我的Offer。我的体会是这些大公司其实并不难进,只要你Java好,英语还过得去,基本问题不大。当然也要看机遇,因为很多人得不到面试机会。 另外想问一下这个论坛有IBM CSTL的吗?在里面做Java开发是否有前途?好像是IBM i系列服务器上的管理系统的开发。我还没决定到底去哪家?Oracle是做ERP方面的开发的,做项目。也请大家能给我一些意见。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。

推荐链接

牛人!把面试的具体过程贡献一下。 返回顶楼 回帖地址

0 0 请登录后投票 * scud

  • 等级: 二钻会员
  • scud的博客
  • 文章: 377
  • 积分: 1296
  • 来自: 北京
  • 发表时间:昨天

IBM, Oracle 简历投过....没面试机会 返回顶楼 回帖地址

0 0 请登录后投票 * kakueiken

  • 等级: 初级会员
  • kakueiken的博客
  • 文章: 54
  • 积分: 30
  • 来自: 温岭
  • 发表时间:昨天

楼主. 请教些IBM面试经验吧. 最近有人内部推荐... 对日的. 你的简历模板是咋样的? 谢谢撒. 返回顶楼 回帖地址

0 0 请登录后投票 * rogerer

  • 等级: 初级会员
  • rogerer的博客
  • 文章: 4
  • 积分: 30
  • 来自: 上海
  • 发表时间:昨天

阁下是位牛人。 因为不是很清楚你的具体情况,想要出出注意,也是比较困难的。⊙﹏⊙b汗 好运! 返回顶楼 回帖地址

0 0 请登录后投票 * herryhaixiao

确实是位大牛,外企,渴望不可及 返回顶楼 回帖地址

0 0 请登录后投票 * WorldHello

  • 等级: 初级会员
  • WorldHello的博客
  • 文章: 205
  • 积分: 50
  • 来自: 北京
  • 发表时间:昨天

yangstarfly 写道

我是Javaeye的老会员了,好久没来发帖了。最近正好找工作,想和大家分享一下。在我面试过的公司中,最有名的是IBM, Oracle, 百度。目前已经拿到IBM CSTL, Oracle北京研发中心的Offer。到底去哪家我还没想好。 IBM的面试经历比较简单。只有2轮面试。每轮都是技术+英语。一个月后通知我拿到Offer. Oracle三轮面试+一轮电面,除了电面外,每轮都有英语对话。也差不多是一个月后给我的Offer。我的体会是这些大公司其实并不难进,只要你Java好,英语还过得去,基本问题不大。当然也要看机遇,因为很多人得不到面试机会。 另外想问一下这个论坛有IBM CSTL的吗?在里面做Java开发是否有前途?好像是IBM i系列服务器上的管理系统的开发。我还没决定到底去哪家?Oracle是做ERP方面的开发的,做项目。也请大家能给我一些意见。 oracle只有13薪,有时还不到 ibm 14.5薪,每月有万能的800补助 返回顶楼 回帖地址

0 0 请登录后投票 * mercyblitz

  • 等级: 初级会员
  • mercyblitz的博客
  • 文章: 389
  • 积分: 30
  • 来自: 长沙市
  • 发表时间:昨天

WorldHello 写道

yangstarfly 写道

我是Javaeye的老会员了,好久没来发帖了。最近正好找工作,想和大家分享一下。在我面试过的公司中,最有名的是IBM, Oracle, 百度。目前已经拿到IBM CSTL, Oracle北京研发中心的Offer。到底去哪家我还没想好。 IBM的面试经历比较简单。只有2轮面试。每轮都是技术+英语。一个月后通知我拿到Offer. Oracle三轮面试+一轮电面,除了电面外,每轮都有英语对话。也差不多是一个月后给我的Offer。我的体会是这些大公司其实并不难进,只要你Java好,英语还过得去,基本问题不大。当然也要看机遇,因为很多人得不到面试机会。 另外想问一下这个论坛有IBM CSTL的吗?在里面做Java开发是否有前途?好像是IBM i系列服务器上的管理系统的开发。我还没决定到底去哪家?Oracle是做ERP方面的开发的,做项目。也请大家能给我一些意见。 oracle只有13薪,有时还不到 ibm 14.5薪,每月有万能的800补助 万能是什么意思? 返回顶楼 回帖地址

0 0 请登录后投票 * forchenyun

  • 等级: 初级会员
  • forchenyun的博客
  • 文章: 257
  • 积分: 0
  • 来自: 杭州
  • 发表时间:昨天

说一下待遇6,好比较 返回顶楼 回帖地址

0 0 请登录后投票 * sharong

  • 等级: 一星会员
  • sharong的博客
  • 文章: 205
  • 积分: 149
  • 来自: 北京
  • 发表时间:昨天

4月底被quickr team拒掉的loser飘过。。。 返回顶楼 回帖地址

0 0 请登录后投票

« 上一页 1 2 3 下一页 » 论坛首页招聘求职版职场话题 跳转论坛:Java编程和Java企业应用 Web前端技术 移动编程和手机应用开发 C/C++编程 Ruby编程 Python编程 PHP编程 Flash编程和RIA Microsoft .Net 综合技术 软件开发和项目管理 行业应用 入门讨论 招聘求职 海阔天空

© 2003-2010 JavaEye.com. 上海炯耐计算机软件有限公司版权所有 [ 沪ICP备05023328号 ]

我在Oracle和IBM的面试经历讨论第2页

Posted on

我在Oracle和IBM的面试经历讨论第2页

您还未登录 ! 我的应用 登录 注册

JavaEye-最棒的软件开发交流社区

论坛首页招聘求职版职场话题

我在Oracle和IBM的面试经历

全部 企业点评 职场话题 求职经验 面试秘籍 招聘职位

myApps快速开发平台,配置即开发、所见即所得,节约85%工作量

« 上一页 1 2 3 下一页 » 浏览 5251 次 主题:我在Oracle和IBM的面试经历

精华帖 (0) :: 良好帖 (0) :: 隐藏帖 (0) 作者 正文 * BloodyCoder

  • 等级: 初级会员
  • BloodyCoder的博客
  • 文章: 46
  • 积分: 30
  • 来自: 北京
  • 发表时间:昨天

< > 猎头职位:楼主是研究生吧 返回顶楼 回帖地址

0 0 请登录后投票 * Hedgehog

  • 等级: 初级会员
  • Hedgehog的博客
  • 文章: 7
  • 积分: 30
  • 来自: 黑户群体
  • 发表时间:昨天

大公司没有文凭几乎是没有面试机会的吧,除非内推。 返回顶楼 回帖地址

0 0 请登录后投票 * sunofsummer

  • 等级: 初级会员
  • sunofsummer的博客
  • 文章: 9
  • 积分: 30
  • 来自: 吉林
  • 发表时间:昨天

确实是位牛人。 返回顶楼 回帖地址

0 0 请登录后投票 * yangstarfly

  • 等级: 四星会员
  • yangstarfly的博客
  • 文章: 88
  • 积分: 417
  • 来自: 北京
  • 发表时间:24 小时前 最后修改:24 小时前

我是楼主,看到这么多人回复,我再说一些我的基本情况。我是硕士学历,5年工作经验。薪水方面来说,IBM的稍微多一些,主要是多了一个15%的saving fund。 关于面试经验,我不能透露具体的面试题。我想说的是,主要是要基础知识雄厚,基本功要好。只会SSH框架是不行的。 返回顶楼 回帖地址

0 0 请登录后投票 * yschen

  • 等级: 初级会员
  • yschen的博客
  • 文章: 47
  • 积分: 30
  • 来自: 广州
  • 发表时间:24 小时前

确实,搞JAVA的一定要内功深厚,不然很难上升到更高的层次,管理能力好一些的,可以做个优秀的PM,不然,到了一定经验,就很难上升了. 正在提高内功中....... 返回顶楼 回帖地址

0 0 请登录后投票 * freej

  • 等级: 初级会员
  • freej的博客
  • 文章: 420
  • 积分: 40
  • 来自: 北京
  • 发表时间:24 小时前

yangstarfly 写道

我是楼主,看到这么多人回复,我再说一些我的基本情况。我是硕士学历,5年工作经验。薪水方面来说,IBM的稍微多一些,主要是多了一个15%的saving fund。 关于面试经验,我不能透露具体的面试题。我想说的是,主要是要基础知识雄厚,基本功要好。只会SSH框架是不行的。 你要在IBM待满年数的话,saving fund倒是很管用。Oracle我不知道,IBM你进去的话,会慢慢变蓝的,也就是说做事情更程式化、更流程一些,具体的自己体会吧。另一个职位,光看ERP和做项目这两个词,第一感觉更像是面向业务的。这样的话,一个是做产品,一个是做行业。在这方面觉得你也需要做个选择。其他方面,既然都是大型外企,除了你所说的工资,其他的就只有企业文化不同了,应该是仅此而已。 返回顶楼 回帖地址

0 0 请登录后投票 * woshizn

  • 等级: 初级会员
  • woshizn的博客
  • 文章: 64
  • 积分: 30
  • 来自: 成都
  • 发表时间:23 小时前

不清楚 返回顶楼 回帖地址

0 0 请登录后投票 * whaosoft

  • 等级: 一星会员
  • whaosoft的博客
  • 文章: 2407
  • 积分: 100
  • 来自: 天津
  • 发表时间:20 小时前

果然牛人 那些公司 我都不敢想 返回顶楼 回帖地址

0 0 请登录后投票 * lkj107

  • 等级: 初级会员
  • lkj107的博客
  • 文章: 882
  • 积分: 40
  • 来自: 石家庄
  • 发表时间:20 小时前

目标 内推和投简历是不是面试过程不一样啊 返回顶楼 回帖地址

0 0 请登录后投票 * ajonjun

  • 等级: 初级会员
  • ajonjun的博客
  • 文章: 59
  • 积分: 0
  • 来自: 深圳
  • 发表时间:17 小时前 最后修改:17 小时前

楼主果然是牛,这么轻而易举的拿到Offer了。要是能分享下详细的过程就好了。 返回顶楼 回帖地址

0 0 请登录后投票

« 上一页 1 2 3 下一页 » 论坛首页招聘求职版职场话题 跳转论坛:Java编程和Java企业应用 Web前端技术 移动编程和手机应用开发 C/C++编程 Ruby编程 Python编程 PHP编程 Flash编程和RIA Microsoft .Net 综合技术 软件开发和项目管理 行业应用 入门讨论 招聘求职 海阔天空

© 2003-2010 JavaEye.com. 上海炯耐计算机软件有限公司版权所有 [ 沪ICP备05023328号 ]

ThoughtWorks 的一道笔试题

Posted on

ThoughtWorks 的一道笔试题 - blog - CSDN博客

blog

凡所有相,皆是虚妄,若见诸相非相,即见如来

*

用户操作 [留言] [发消息] [加为好友] 订阅我的博客 XML聚合 FeedSky 订阅到鲜果 订阅到Google 订阅到抓虾[编辑]passos的公告 [编辑]文章分类 * (RSS)01010101

原创 ThoughtWorks 的一道笔试题 收藏

PROBLEM ONE: TRAINS Problem: The local commuter railroad services a number of towns in Kiwiland. Because of monetary concerns, all of the tracks are 'one-way.' That is, a route from Kaitaia to Invercargill does not imply the existence of a route from Invercargill to Kaitaia. In fact, even if both of these routes do happen to exist, they are distinct and are not necessarily the same distance! The purpose of this problem is to help the railroad provide its customers with information about the routes. In particular, you will compute the distance along a certain route, the number of different routes between two towns, and the shortest route between two towns. Input: A directed graph where a node represents a town and an edge represents a route between two towns. The weighting of the edge represents the distance between the two towns. A given route will never appear more than once, and for a given route, the starting and ending town will not be the same town. Output: For test input 1 through 5, if no such route exists, output 'NO SUCH ROUTE'. Otherwise, follow the route as given; do not make any extra stops! For example, the first problem means to start at city A, then travel directly to city B (a distance of 5), then directly to city C (a distance of 4).

  1. The distance of the route A-B-C.
  2. The distance of the route A-D.
  3. The distance of the route A-D-C.
  4. The distance of the route A-E-B-C-D.
  5. The distance of the route A-E-D.
  6. The number of trips starting at C and ending at C with a maximum of 3 stops. In the sample data below, there are two such trips: C-D-C (2 stops). and C-E-B-C (3 stops).
  7. The number of trips starting at A and ending at C with exactly 4 stops. In the sample data below, there are three such trips: A to C (via B,C,D); A to C (via D,C,D); and A to C (via D,E,B).
  8. The length of the shortest route (in terms of distance to travel) from A to C.
  9. The length of the shortest route (in terms of distance to travel) from B to B.
  10. The number of different routes from C to C with a distance of less than 30. In the sample data, the trips are: CDC, CEBC, CEBCDC, CDCEBC, CDEBC, CEBCEBC, CEBCEBCEBC. Test Input: For the test input, the towns are named using the first few letters of the alphabet from A to D. A route between two towns (A to B) with a distance of 5 is represented as AB5. Graph: AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7 Expected Output: Output /#1: 9 Output /#2: 5 Output /#3: 13 Output /#4: 22 Output /#5: NO SUCH ROUTE Output /#6: 2 Output /#7: 3 Output /#8: 9 Output /#9: 9

    Output /#10: 7

简单来说,就是一个图的搜索问题。用数组来表示图,简化之后大致的解决方案都差不多。

6:

  1. public class Graphmain { 1.
  2. public int[][] map = {
  3. {-1, 5, -1, 5, 7},
  4. {-1, -1, 4, -1, -1},
  5. {-1, -1, -1, 8, 2},
  6. {-1, -1, 8, -1, 6},
  7. {-1, 3, -1, -1, -1},
  8. };
  9. public void dfs(String end, String path, int maxLength)
  10. {
  11. if (path.length() - 1 > maxLength) return;
  12. if ( path.length() > 1 && path.endsWith(end) ) {
  13. System.out.println(path + ", " + path.length());
  14. }
  15. char lastChar = path.charAt(path.length()-1);
  16. int lastNodeIndex = lastChar - 'A';
  17. for ( int i=0; i<map[lastNodeIndex].length; i++ )
  18. {
  19. char newChar = (char)(i + 'A');
  20. if ( map[lastNodeIndex][i] > 0) {
  21. dfs(end, path + newChar, maxLength);
  22. }
  23. }
  24. }
  25. public static void main(String[] args) {
  26. Graphmain g = new Graphmain();
  27. g.dfs("C", "C", 3);
  28. }
  29. } 1.

7:

  1. public class Graphmain { 1.
  2. public int[][] map = {
  3. { -1, 5, -1, 5, 7 },
  4. { -1, -1, 4, -1, -1 },
  5. { -1, -1, -1, 8, 2 },
  6. { -1, -1, 8, -1, 6 },
  7. { -1, 3, -1, -1, -1 }
  8. }; 1.
  9. public void bfs(String start, String end, int hops) {
  10. String lastRoute = start; 1.
  11. for (int hop = 0; hop < hops; hop++) {
  12. String route = "";
  13. for (int i = 0; i < lastRoute.length(); i++) {
  14. char c = lastRoute.charAt(i);
  15. int id = c - 'A'; 1.
  16. for (int j = 0; j < map[id].length; j++) {
  17. if (map[id][j] > 0)
  18. route = route + (char) (j + 'A');
  19. }
  20. }
  21. // System.out.println(lastRoute);
  22. lastRoute = route;
  23. } 1.
  24. // System.out.println(lastRoute);
  25. System.out.println(lastRoute.split(end).length - 1);
  26. } 1.
  27. public static void main(String[] args) {
  28. Graphmain g = new Graphmain(); 1.
  29. g.bfs("A", "C", 4);
  30. }
  31. } 1.

8/9:

  1. public class Graphmain { 1.
  2. public int[][] map = {
  3. {-1, 5, -1, 5, 7},
  4. {-1, -1, 4, -1, -1},
  5. {-1, -1, -1, 8, 2},
  6. {-1, -1, 8, -1, 6},
  7. {-1, 3, -1, -1, -1},
  8. };
  9. public void dfs(String end, String path, int cost) {
  10. if (path.endsWith(end) && cost < bestCost && cost > 0) {
  11. bestPath = path;
  12. bestCost = cost;
  13. return;
  14. }
  15. char lastChar = path.charAt(path.length() - 1);
  16. int lastNodeIndex = lastChar - 'A'; 1.
  17. for (int i = 0; i < map[lastNodeIndex].length; i++) {
  18. char newChar = (char) (i + 'A');
  19. int newCost = map[lastNodeIndex][i];
  20. if (newCost > 0) {
  21. if (path.indexOf(newChar) > 0)
  22. continue;
  23. dfs(end, path + newChar, cost + newCost);
  24. }
  25. }
  26. } 1.
  27. public String bestPath = "";
  28. public int bestCost = Integer.MAX_VALUE; 1.
  29. public static void main(String[] args) {
  30. Graphmain g = new Graphmain(); 1.
  31. g.dfs("C", "A", 0); // 8
  32. // g.dfs("B", "B", 0); // 9 1.
  33. System.out.println("Best Path: " + g.bestPath + "\nCost: " + g.bestCost);
  34. }
  35. } 1.

10:

  1. public class Graphmain { 1.
  2. public int[][] map = {
  3. {-1, 5, -1, 5, 7},
  4. {-1, -1, 4, -1, -1},
  5. {-1, -1, -1, 8, 2},
  6. {-1, -1, 8, -1, 6},
  7. {-1, 3, -1, -1, -1},
  8. };
  9. public void dfs(String end, String path, int cost) {
  10. if (cost >= 30)
  11. return; 1.
  12. if (cost > 0 && path.endsWith(end)) {
  13. System.out.println(path + ", " + cost);
  14. } 1.
  15. char lastChar = path.charAt(path.length() - 1);
  16. int lastNodeIndex = lastChar - 'A'; 1.
  17. for (int i = 0; i < map[lastNodeIndex].length; i++) {
  18. char newChar = (char) (i + 'A');
  19. int newCost = map[lastNodeIndex][i];
  20. if (newCost > 0) {
  21. dfs(end, path + newChar, cost + newCost);
  22. }
  23. }
  24. } 1.
  25. public static void main(String[] args) {
  26. Graphmain g = new Graphmain(); 1.
  27. g.dfs("C", "C", 0);
  28. }
  29. } 1.

发表于 @ 2008年12月11日 15:30:00 | 评论( loading... )| 编辑| 举报| 收藏

旧一篇:Android源码构建工具速览(二)—— 清单文件 | 新一篇:为什么cpio要比tar好

查看最新精华文章 请访问博客首页相关文章

热门招聘职位

代码难道不是这么写的?讨论第18页

Posted on

代码难道不是这么写的?讨论第18页 - Java综合 - Java - JavaEye论坛

您还未登录 ! 我的应用 登录 注册

JavaEye-最棒的软件开发交流社区

论坛首页Java编程和Java企业应用版Java综合

代码难道不是这么写的?

全部 Hibernate Spring Struts iBATIS 企业应用 设计模式 DAO 领域模型 OO Tomcat SOA JBoss Swing Java综合

myApps快速开发平台,配置即开发、所见即所得,节约85%工作量

« 上一页 1 217 18 19 20 下一页 » 浏览 21808 次 主题:代码难道不是这么写的?

该帖已经被评为良好帖 作者 正文 * moonranger

  • 等级: 初级会员
  • moonranger的博客
  • 文章: 44
  • 积分: 40
  • 来自: 天津
  • 发表时间:2010-07-30

< > 猎头职位:

qiushily2030 写道 fengfeng925 写道

qiushily2030 写道

A a; 申明在内部,每次遍历都申明一个a的变量.
申明在外面 只申明一次 一直复用. 申明也是要资源的.. 一个变量就相当于一个指针,循环1亿次,LZ你说呢. 评审官说的还是有理的,不过这个得看需求. JVM回收是在内存不足的时候. 还是不要想当然了,我就那么干过一回. 程序是最真实的答案... 简直是TMD胡扯。 JVM回收是在内存不足的时候.这个已经修正. 不是内存不足才调用。。 你说我胡扯? 那for里定义的局部变量放哪里?不要也和上面一个的观点一样:只申明一次,后调用索引. 这个我不可理解。。 方法的参数连同方法里的变量所占用的空间,在编译时就已经确定了,它决定了运行时一个方法被调用的时侯要分配多大的栈帧。一个变量放在循环外还是循环里,只是在编译期限定了其作用域而已,到了运行时是没有区别的(也许只是在栈帧的local variables区里的位置不同)。 看一下方法的字节码,一切都非常明了: private final int[] numbers = {1, 2, 3, 4, 5}; public void varOutsideLoop() { int n; for (int i = 0; i < numbers.length; i++) { n = numbers[i]; System.out.println(n); } } public void varInsideLoop() { for (int i = 0; i < numbers.length; i++) { int n = numbers[i]; System.out.println(n); } } 对应的字节码: public void varOutsideLoop(); Signature: ()V Code: Stack=2, Locals=3, Args_size=1 0: iconst_0 1: istore_2 2: goto 22 5: aload_0 6: getfield /#12; //Field numbers:[I 9: iload_2 10: iaload 11: istore_1 12: getstatic /#19; //Field java/lang/System.out:Ljava/io/PrintStream; 15: iload_1 16: invokevirtual /#25; //Method java/io/PrintStream.println:(I)V 19: iinc 2, 1 22: iload_2 23: aload_0 24: getfield /#12; //Field numbers:[I 27: arraylength 28: if_icmplt 5 31: return LineNumberTable: line 43: 0 line 44: 5 line 45: 12 line 43: 19 line 47: 31 LocalVariableTable: Start Length Slot Name Signature 0 32 0 this Lcom/jstudio/learnjvm/classloader/VarInLoop; 12 10 1 n I 2 29 2 i I public void varInsideLoop(); Signature: ()V Code: Stack=2, Locals=3, Args_size=1 0: iconst_0 1: istore_1 2: goto 22 5: aload_0 6: getfield /#12; //Field numbers:[I 9: iload_1 10: iaload 11: istore_2 12: getstatic /#19; //Field java/lang/System.out:Ljava/io/PrintStream; 15: iload_2 16: invokevirtual /#25; //Method java/io/PrintStream.println:(I)V 19: iinc 1, 1 22: iload_1 23: aload_0 24: getfield /#12; //Field numbers:[I 27: arraylength 28: if_icmplt 5 31: return LineNumberTable: line 50: 0 line 51: 5 line 52: 12 line 50: 19 line 54: 31 LocalVariableTable: Start Length Slot Name Signature 0 32 0 this Lcom/jstudio/learnjvm/classloader/VarInLoop; 2 29 1 i I 12 7 2 n I 仔细看字节码就能发现,除了n和循环变量i在local variable table中的位置不同,其他的所有的都没有区别。 varOutsideLoop那个方法里我故意没有初始化n,如果加上初始化,就会多一条iconst和一条istore指令。 至于位置不一样的原因,个人猜测与变量出现的位置有关,n在循环外的版本,它出现在前,所以占据了第一个slot(第0个slot是对象本身,即this);n在循环里的版本,循环变量i出现在前,所以i占据了第一个slot,而n占用的是第二个slot。 除此之外,两个方法没有任何的区别。 mercyblitz 写道

主要你误解了a变量在遍历中,有入栈和出栈的操作。并没有重复开辟局部变量,再说JVM优化之后,不会重复创建。 个人认为这种说法也不太对,在一个方法内部不会有所谓的“入栈”和“出栈”操作。方法里,一个变量占用一个local variable table的slot,一个萝卜一个坑。所有这些变量都是在方法结束,堆栈帧被销毁的时侯才真正被“回收”,即使方法结束的时侯它早以超出了自己的作用域…… 实践中,变量的作用域当然是尽可能小才好,即有利于垃圾收集、也消除了一些潜在的导致bug的隐患。 楼主别理那个“代码评审官”就好……话说如果我遇到这种人这种事,我八成不愿继续干下去…… 返回顶楼 回帖地址

5 0 请登录后投票 * mercyblitz

  • 等级: 初级会员
  • mercyblitz的博客
  • 文章: 465
  • 积分: 30
  • 来自: 长沙市
  • 发表时间:2010-07-30

moonranger 写道

qiushily2030 写道

fengfeng925 写道

qiushily2030 写道

A a; 申明在内部,每次遍历都申明一个a的变量.
申明在外面 只申明一次 一直复用. 申明也是要资源的.. 一个变量就相当于一个指针,循环1亿次,LZ你说呢. 评审官说的还是有理的,不过这个得看需求. JVM回收是在内存不足的时候. 还是不要想当然了,我就那么干过一回. 程序是最真实的答案... 简直是TMD胡扯。 JVM回收是在内存不足的时候.这个已经修正. 不是内存不足才调用。。 你说我胡扯? 那for里定义的局部变量放哪里?不要也和上面一个的观点一样:只申明一次,后调用索引. 这个我不可理解。。 方法的参数连同方法里的变量所占用的空间,在编译时就已经确定了,它决定了运行时一个方法被调用的时侯要分配多大的栈帧。一个变量放在循环外还是循环里,只是在编译期限定了其作用域而已,到了运行时是没有区别的(也许只是在栈帧的local variables区里的位置不同)。 看一下方法的字节码,一切都非常明了: private final int[] numbers = {1, 2, 3, 4, 5}; public void varOutsideLoop() { int n; for (int i = 0; i < numbers.length; i++) { n = numbers[i]; System.out.println(n); } } public void varInsideLoop() { for (int i = 0; i < numbers.length; i++) { int n = numbers[i]; System.out.println(n); } } 对应的字节码: public void varOutsideLoop(); Signature: ()V Code: Stack=2, Locals=3, Args_size=1 0: iconst_0 1: istore_2 2: goto 22 5: aload_0 6: getfield /#12; //Field numbers:[I 9: iload_2 10: iaload 11: istore_1 12: getstatic /#19; //Field java/lang/System.out:Ljava/io/PrintStream; 15: iload_1 16: invokevirtual /#25; //Method java/io/PrintStream.println:(I)V 19: iinc 2, 1 22: iload_2 23: aload_0 24: getfield /#12; //Field numbers:[I 27: arraylength 28: if_icmplt 5 31: return LineNumberTable: line 43: 0 line 44: 5 line 45: 12 line 43: 19 line 47: 31 LocalVariableTable: Start Length Slot Name Signature 0 32 0 this Lcom/jstudio/learnjvm/classloader/VarInLoop; 12 10 1 n I 2 29 2 i I public void varInsideLoop(); Signature: ()V Code: Stack=2, Locals=3, Args_size=1 0: iconst_0 1: istore_1 2: goto 22 5: aload_0 6: getfield /#12; //Field numbers:[I 9: iload_1 10: iaload 11: istore_2 12: getstatic /#19; //Field java/lang/System.out:Ljava/io/PrintStream; 15: iload_2 16: invokevirtual /#25; //Method java/io/PrintStream.println:(I)V 19: iinc 1, 1 22: iload_1 23: aload_0 24: getfield /#12; //Field numbers:[I 27: arraylength 28: if_icmplt 5 31: return LineNumberTable: line 50: 0 line 51: 5 line 52: 12 line 50: 19 line 54: 31 LocalVariableTable: Start Length Slot Name Signature 0 32 0 this Lcom/jstudio/learnjvm/classloader/VarInLoop; 2 29 1 i I 12 7 2 n I 仔细看字节码就能发现,除了n和循环变量i在local variable table中的位置不同,其他的所有的都没有区别。 varOutsideLoop那个方法里我故意没有初始化n,如果加上初始化,就会多一条iconst和一条istore指令。 至于位置不一样的原因,个人猜测与变量出现的位置有关,n在循环外的版本,它出现在前,所以占据了第一个slot(第0个slot是对象本身,即this);n在循环里的版本,循环变量i出现在前,所以i占据了第一个slot,而n占用的是第二个slot。 除此之外,两个方法没有任何的区别。 mercyblitz 写道

主要你误解了a变量在遍历中,有入栈和出栈的操作。并没有重复开辟局部变量,再说JVM优化之后,不会重复创建。 个人认为这种说法也不太对,在一个方法内部不会有所谓的“入栈”和“出栈”操作。方法里,一个变量占用一个local variable table的slot,一个萝卜一个坑。所有这些变量都是在方法结束,堆栈帧被销毁的时侯才真正被“回收”,即使方法结束的时侯它早以超出了自己的作用域…… 实践中,变量的作用域当然是尽可能小才好,即有利于垃圾收集、也消除了一些潜在的导致bug的隐患。 楼主别理那个“代码评审官”就好……话说如果我遇到这种人这种事,我八成不愿继续干下去…… 恩,谢谢指正,我也仔细想了一下。在楼主的例子中,字节码说明两个局部变量指向不同的地方。不会重复开辟。要想开辟更多,哪么需要不同名称的变量申明。 返回顶楼 回帖地址

0 0 请登录后投票 * cisumer

  • 等级: 初级会员
  • cisumer的博客
  • 文章: 4
  • 积分: 30
  • 来自: 上海
  • 发表时间:2010-07-30

ei0 写道

我只对s感兴趣!!! 返回顶楼 回帖地址

0 2 请登录后投票 * beneo

  • 等级: 初级会员
  • beneo的博客
  • 文章: 115
  • 积分: 50
  • 来自: 希伯來
  • 发表时间:2010-07-30

mercyblitz 写道

moonranger 写道

qiushily2030 写道

fengfeng925 写道

qiushily2030 写道

A a; 申明在内部,每次遍历都申明一个a的变量.
申明在外面 只申明一次 一直复用. 申明也是要资源的.. 一个变量就相当于一个指针,循环1亿次,LZ你说呢. 评审官说的还是有理的,不过这个得看需求. JVM回收是在内存不足的时候. 还是不要想当然了,我就那么干过一回. 程序是最真实的答案... 简直是TMD胡扯。 JVM回收是在内存不足的时候.这个已经修正. 不是内存不足才调用。。 你说我胡扯? 那for里定义的局部变量放哪里?不要也和上面一个的观点一样:只申明一次,后调用索引. 这个我不可理解。。 方法的参数连同方法里的变量所占用的空间,在编译时就已经确定了,它决定了运行时一个方法被调用的时侯要分配多大的栈帧。一个变量放在循环外还是循环里,只是在编译期限定了其作用域而已,到了运行时是没有区别的(也许只是在栈帧的local variables区里的位置不同)。 看一下方法的字节码,一切都非常明了: private final int[] numbers = {1, 2, 3, 4, 5}; public void varOutsideLoop() { int n; for (int i = 0; i < numbers.length; i++) { n = numbers[i]; System.out.println(n); } } public void varInsideLoop() { for (int i = 0; i < numbers.length; i++) { int n = numbers[i]; System.out.println(n); } } 对应的字节码: public void varOutsideLoop(); Signature: ()V Code: Stack=2, Locals=3, Args_size=1 0: iconst_0 1: istore_2 2: goto 22 5: aload_0 6: getfield /#12; //Field numbers:[I 9: iload_2 10: iaload 11: istore_1 12: getstatic /#19; //Field java/lang/System.out:Ljava/io/PrintStream; 15: iload_1 16: invokevirtual /#25; //Method java/io/PrintStream.println:(I)V 19: iinc 2, 1 22: iload_2 23: aload_0 24: getfield /#12; //Field numbers:[I 27: arraylength 28: if_icmplt 5 31: return LineNumberTable: line 43: 0 line 44: 5 line 45: 12 line 43: 19 line 47: 31 LocalVariableTable: Start Length Slot Name Signature 0 32 0 this Lcom/jstudio/learnjvm/classloader/VarInLoop; 12 10 1 n I 2 29 2 i I public void varInsideLoop(); Signature: ()V Code: Stack=2, Locals=3, Args_size=1 0: iconst_0 1: istore_1 2: goto 22 5: aload_0 6: getfield /#12; //Field numbers:[I 9: iload_1 10: iaload 11: istore_2 12: getstatic /#19; //Field java/lang/System.out:Ljava/io/PrintStream; 15: iload_2 16: invokevirtual /#25; //Method java/io/PrintStream.println:(I)V 19: iinc 1, 1 22: iload_1 23: aload_0 24: getfield /#12; //Field numbers:[I 27: arraylength 28: if_icmplt 5 31: return LineNumberTable: line 50: 0 line 51: 5 line 52: 12 line 50: 19 line 54: 31 LocalVariableTable: Start Length Slot Name Signature 0 32 0 this Lcom/jstudio/learnjvm/classloader/VarInLoop; 2 29 1 i I 12 7 2 n I 仔细看字节码就能发现,除了n和循环变量i在local variable table中的位置不同,其他的所有的都没有区别。 varOutsideLoop那个方法里我故意没有初始化n,如果加上初始化,就会多一条iconst和一条istore指令。 至于位置不一样的原因,个人猜测与变量出现的位置有关,n在循环外的版本,它出现在前,所以占据了第一个slot(第0个slot是对象本身,即this);n在循环里的版本,循环变量i出现在前,所以i占据了第一个slot,而n占用的是第二个slot。 除此之外,两个方法没有任何的区别。 mercyblitz 写道

主要你误解了a变量在遍历中,有入栈和出栈的操作。并没有重复开辟局部变量,再说JVM优化之后,不会重复创建。 个人认为这种说法也不太对,在一个方法内部不会有所谓的“入栈”和“出栈”操作。方法里,一个变量占用一个local variable table的slot,一个萝卜一个坑。所有这些变量都是在方法结束,堆栈帧被销毁的时侯才真正被“回收”,即使方法结束的时侯它早以超出了自己的作用域…… 实践中,变量的作用域当然是尽可能小才好,即有利于垃圾收集、也消除了一些潜在的导致bug的隐患。 楼主别理那个“代码评审官”就好……话说如果我遇到这种人这种事,我八成不愿继续干下去…… 恩,谢谢指正,我也仔细想了一下。在楼主的例子中,字节码说明两个局部变量指向不同的地方。不会重复开辟。要想开辟更多,哪么需要不同名称的变量申明。 第一个是frame append 第二个是frame same 所以还是有些许区别的吧 返回顶楼 回帖地址

0 0 请登录后投票 * RednaxelaFX

  • 等级: 五星会员
  • RednaxelaFX的博客
  • 文章: 385
  • 积分: 790
  • 来自: 杭州
  • 发表时间:2010-07-30 最后修改:2010-07-30

moonranger 写道

mercyblitz 写道

主要你误解了a变量在遍历中,有入栈和出栈的操作。并没有重复开辟局部变量,再说JVM优化之后,不会重复创建。 个人认为这种说法也不太对,在一个方法内部不会有所谓的“入栈”和“出栈”操作。方法里,一个变量占用一个local variable table的slot,一个萝卜一个坑。所有这些变量都是在方法结束,堆栈帧被销毁的时侯才真正被“回收”,即使方法结束的时侯它早以超出了自己的作用域…… ECMA-335 CLI是规定方法中每个局部变量占用局部变量区的一个坑,不在方法中复用局部变量区。但它在设计之初就是倾向于使用JIT编译器来实现执行引擎的;虽然中间代码(CIL)中局部变量不复用局部变量区的坑,但实际JIT编译后的代码不关心这个,局部变量的存储分配(栈/寄存器)还是有复用。可以参考.NET CLR的实现。 (以下说明针对概念中的Java虚拟机) Java虚拟机在设计之初就同时考虑到要能方便的用解释器或JIT编译器来实现。解释器一般做的优化较少,执行过程与字节码中指定的方式基本是直接对应的,所以字节码上就已经需要考虑到实际执行的情况了。Java虚拟机的局部变量区是可复用的,在同一方法里作用域不交叠的局部变量可以分配在同一个局部变量区的slot上。有兴趣的话可以自己做实验验证,也可以参考之前我做的分享的演示稿,20100621的版本。 例子的话,可以看这么一段代码: public class LocalsDemo { // locals = 5 public static void main(String[] args) { // args in slot 0 int a = 1; // a in slot 1 int b = 2; // b in slot 2 { long c = 3; // c in slot 3 (to slot 4) } { int d = 4; // d in slot 3 int e = 5; // e in slot 4 } for (int i = 0; i < 3; i++) { // i in slot 3 int j = i + 1; // j in slot 4 } } } main()方法编译后对应的字节码和元信息是: public static void main(java.lang.String[]); Code: Stack=2, Locals=5, Args_size=1 0: iconst_1 1: istore_1 2: iconst_2 3: istore_2 4: ldc2_w /#2; //long 3l 7: lstore_3 8: iconst_4 9: istore_3 10: iconst_5 11: istore 4 13: iconst_0 14: istore_3 15: iload_3 16: iconst_3 17: if_icmpge 31 20: iload_3 21: iconst_1 22: iadd 23: istore 4 25: iinc 3, 1 28: goto 15 31: return LineNumberTable: line 4: 0 line 5: 2 line 7: 4 line 10: 8 line 11: 10 line 13: 13 line 14: 20 line 13: 25 line 16: 31 LocalVariableTable: Start Length Slot Name Signature 8 0 3 c J 10 3 3 d I 13 0 4 e I 25 0 4 j I 15 16 3 i I 0 32 0 args [Ljava/lang/String; 2 30 1 a I 4 28 2 b I 要在Class文件里看到LocalVariableTable属性表的话,编译Java源码时请加上-g参数。 Java虚拟机中, 方法调用涉及的栈帧push/pop是对Java栈(Java stack),或者有些文档里叫“Java控制栈”(Java control stack),或者叫“Java方法调用栈”; 在方法中局部变量的写/读操作涉及的push/pop则是对操作数栈(operand stack),或者有些文档叫“表达式栈”(expression stack),或者叫求值栈(evaluation stack)。 两个栈的区别可以参考Java虚拟机规范第二版3.5.23.6.2两个小节,我之前的介绍基于栈/寄存器的虚拟机的帖里也有提到,也可以参考前面说的JVM分享的演示稿。 最后上一老图……逃 返回顶楼 回帖地址

7 0 请登录后投票 * moonranger

  • 等级: 初级会员
  • moonranger的博客
  • 文章: 44
  • 积分: 40
  • 来自: 天津
  • 发表时间:2010-07-30

RednaxelaFX 写道

moonranger 写道

mercyblitz 写道

主要你误解了a变量在遍历中,有入栈和出栈的操作。并没有重复开辟局部变量,再说JVM优化之后,不会重复创建。 个人认为这种说法也不太对,在一个方法内部不会有所谓的“入栈”和“出栈”操作。方法里,一个变量占用一个local variable table的slot,一个萝卜一个坑。所有这些变量都是在方法结束,堆栈帧被销毁的时侯才真正被“回收”,即使方法结束的时侯它早以超出了自己的作用域…… ECMA-335 CLI是规定方法中每个局部变量占用局部变量区的一个坑,不在方法中复用局部变量区。但它在设计之初就是倾向于使用JIT编译器来实现执行引擎的;虽然中间代码(CIL)中局部变量不复用局部变量区的坑,但实际JIT编译后的代码不关心这个,局部变量的存储分配(栈/寄存器)还是有复用。可以参考.NET CLR的实现。 (以下说明针对概念中的Java虚拟机) Java虚拟机在设计之初就同时考虑到要能方便的用解释器或JIT编译器来实现。解释器一般做的优化较少,执行过程与字节码中指定的方式基本是直接对应的,所以字节码上就已经需要考虑到实际执行的情况了。Java虚拟机的局部变量区是可复用的,在同一方法里作用域不交叠的局部变量可以分配在同一个局部变量区的slot上。有兴趣的话可以自己做实验验证,也可以参考之前我做的分享的演示稿,20100621的版本。 例子的话,可以看这么一段代码: public class LocalsDemo { // locals = 5 public static void main(String[] args) { // args in slot 0 int a = 1; // a in slot 1 int b = 2; // b in slot 2 { long c = 3; // c in slot 3 (to slot 4) } { int d = 4; // d in slot 3 int e = 5; // e in slot 4 } for (int i = 0; i < 3; i++) { // i in slot 3 int j = i + 1; // j in slot 4 } } } main()方法编译后对应的字节码和元信息是: public static void main(java.lang.String[]); Code: Stack=2, Locals=5, Args_size=1 0: iconst_1 1: istore_1 2: iconst_2 3: istore_2 4: ldc2_w /#2; //long 3l 7: lstore_3 8: iconst_4 9: istore_3 10: iconst_5 11: istore 4 13: iconst_0 14: istore_3 15: iload_3 16: iconst_3 17: if_icmpge 31 20: iload_3 21: iconst_1 22: iadd 23: istore 4 25: iinc 3, 1 28: goto 15 31: return LineNumberTable: line 4: 0 line 5: 2 line 7: 4 line 10: 8 line 11: 10 line 13: 13 line 14: 20 line 13: 25 line 16: 31 LocalVariableTable: Start Length Slot Name Signature 8 0 3 c J 10 3 3 d I 13 0 4 e I 25 0 4 j I 15 16 3 i I 0 32 0 args [Ljava/lang/String; 2 30 1 a I 4 28 2 b I 要在Class文件里看到LocalVariableTable属性表的话,编译Java源码时请加上-g参数。 Java虚拟机中, 方法调用涉及的栈帧push/pop是对Java栈(Java stack),或者有些文档里叫“Java控制栈”(Java control stack),或者叫“Java方法调用栈”; 在方法中局部变量的读/写操作涉及的push/pop则是对操作数栈(operand stack),或者有些文档叫“表达式栈”(expression stack),或者叫求值栈(evaluation stack)。 两个栈的区别可以参考Java虚拟机规范第二版3.5.23.6.2两个小节,我之前的介绍基于栈/寄存器的虚拟机的帖里也有提到,也可以参考前面说的JVM分享的演示稿。 最后上一老图……逃 还真没有研究到这种程度。学习了! 返回顶楼 回帖地址

2 0 请登录后投票 * linliangyi2007

  • 等级: 一钻会员
  • linliangyi2007的博客
  • 文章: 803
  • 积分: 996
  • 来自: 福州
  • 发表时间:2010-07-30

高人出现了,哈哈哈!! 哪些只懂得代码文本面上搞所谓性能优化的家伙,可以羞愧的匿了~~~ 返回顶楼 回帖地址

0 0 请登录后投票 * murainwood

  • 等级: 初级会员
  • murainwood的博客
  • 文章: 1077
  • 积分: 30
  • 来自: ...
  • 发表时间:2010-07-30

精彩,秒杀! 返回顶楼 回帖地址

0 0 请登录后投票 * 分离的北极熊

  • 等级: 初级会员
  • 分离的北极熊的博客
  • 文章: 19
  • 积分: 30
  • 来自: 北京
  • 发表时间:2010-07-30

太狠了……………… 返回顶楼 回帖地址

0 0 请登录后投票 * lijihuai

  • 等级: 初级会员
  • lijihuai的博客
  • 文章: 8
  • 积分: 30
  • 发表时间:2010-07-30

没事,实际上,编译以后的字节码是一样的 返回顶楼 回帖地址

0 0 请登录后投票

« 上一页 1 217 18 19 20 下一页 » 论坛首页Java编程和Java企业应用版Java综合 跳转论坛:Java编程和Java企业应用 Web前端技术 移动编程和手机应用开发 C/C++编程 Ruby编程 Python编程 PHP编程 Flash编程和RIA Microsoft .Net 综合技术 软件开发和项目管理 行业应用 入门讨论 招聘求职 海阔天空

© 2003-2010 JavaEye.com. 上海炯耐计算机软件有限公司版权所有 [ 沪ICP备05023328号 ]