最近,咱们团队为了进一步提高合作效率,组织了一次趣味分享流动,心愿通过游戏的形式,帮忙技术部门的共事们更好地了解和实际麻利开发的办法。
在这次流动中,“哪种口头形式更麻利”、“为什么采纳这种办法”等关乎麻利概念实践和实际办法的思考被搭档们提出来并公开探讨。作为开发小组的成员,我获益颇多,特将此次流动中的思考总结下来分享给大家,独特成长~
游戏规则
10集体翻30张牌,每个人要把这30张牌的每1张牌都翻一遍,计算第1集体翻完30张牌所消耗的工夫和所有人翻完30张牌所消耗的工夫~
假如每一个红色方块耗时x,每一个橙色方块耗时y,每一个黄色方块耗时z (x, y, z > 0)
计划1: 第n集体必须等第n-1集体翻完所有的30张牌能力开始翻牌,第1集体不必等
那么咱们参考上图的构造,先计算第1~5集体的翻完30张牌的工夫,而后再乘以2就是总计用时(不存在影响工夫的意外状况):
T1 = ((5 + 1) 5 / 2 x + (4 + 1) 4 / 2 y + 25 5 z) * 2 =30x + 20y + 250z
计划2:第n集体必须等第n-1集体翻完第5张牌能力开始翻牌,第1集体不必等;且第n集体必须等第n-1集体翻完第m张牌,能力翻第m张牌,第1集体不必等。
参考上图构造,先计算1 ~ 10集体翻完前5张牌的工夫,而后再计算第10集体翻完6 ~ 25张牌的工夫就是总计用时(不存在影响工夫的意外状况):
T2= ((5 + 1) 5 / 2 x + (4 + 1) 4 / 2 y) 2 + 25 z = 30x + 20y + 25z
计划3:第n集体必须等第n-1集体翻完第m张牌,能力翻第m张牌,第1集体不必等。
参考上图构造:先计算1 ~ 10集体翻完第1张牌的工夫,而后再计算第10集体翻完第2 ~ 5张牌的工夫,最初再加上第10集体翻完第6 ~ 30张牌的工夫就是总计用时(不存在影响工夫的意外状况):T3= 10x + 4y + 25z
最终后果
上面咱们用程序来验证论断的正确性。
假如 x = y = z = 1s,那最终后果应该是:
T1 = 30 + 20 + 250 = 300s
T2 = 30 + 20 + 25 = 75s
T3 = 10 + 4 + 25 = 39s
理论后果:
public class AgileTest { private static final Logger LOGGER = LoggerFactory.getLogger(AgileTest.class); public static void main(String[] args) { long time1 = way1(); long time2 = way2(); long time3 = way3(); LOGGER.info("time1: {} ms", time1); LOGGER.info("time2: {} ms", time2); LOGGER.info("time3: {} ms", time3); } /** * <p>计划1</p> * <p>第n集体必须等第n-1集体翻完所有的30张牌能力开始翻牌,第1集体不必等。</p> * @return 耗时 ms */ public static long way1() { final String way = "way1"; long startTime = System.currentTimeMillis(); // 1.10集体 for (int i = 1; i < 11; i++) { AtomicInteger atomicI = new AtomicInteger(i); // 2.30张牌,每个人翻完30张牌,下集体能力开始 for (int j = 1; j < 31; j++) { node(way, atomicI, j); } } long endTime = System.currentTimeMillis(); return endTime - startTime; } /** * <p>计划2</p> * <p>第n集体必须等第n-1集体翻完第5张牌能力开始翻牌,第1集体不必等;且第n集体必须等第n-1集体翻完第m张牌,能力翻第m张牌,第1集体不必等。</p> * @return 耗时 ms */ public static long way2() { final String way = "way2"; long startTime = System.currentTimeMillis(); CountDownLatch latch = new CountDownLatch(10); Map<Integer, Integer> map = new ConcurrentHashMap<>(); // 1.10集体 for (int outUser = 1; outUser < 11; outUser++) { int outLastUser = outUser - 1; Integer lastOutUserNode = 0; // 2.每个人必须等后面那个人翻完5张牌能力开始翻牌,第1集体例外 while (outUser != 1 && ((lastOutUserNode = map.get(outLastUser)) == null || lastOutUserNode < 5)) { } AtomicInteger atomicI = new AtomicInteger(outUser); Thread thread = new Thread(() -> { try { int innerUser = atomicI.get(); int lastInnerUser = innerUser - 1; // 3.30张牌 for (int j = 1; j < 31; j++) { // 4.翻牌的速度不能超过前1集体,第1集体例外,第30张除外 Integer lastInnerUserNode = 0; while (innerUser != 1 && ((lastInnerUserNode = map.get(lastInnerUser)) == null || lastInnerUserNode < j)) { } node(way, atomicI, j); map.put(innerUser, j); } } catch (Exception e) { LOGGER.error("Current Thread: " + Thread.currentThread().getName() + "+, exception: ", e); } finally { latch.countDown(); } }, "thread-user-" + outUser); thread.start(); } try { latch.await(); } catch (InterruptedException e) { LOGGER.error("wait thread exception: ", e); } long endTime = System.currentTimeMillis(); return endTime - startTime; } /** * <p>计划3</p> * <p>第n集体必须等第n-1集体翻完第m张牌,能力翻第m张牌,第1集体不必等。</p> * @return 耗时 ms */ public static long way3() { final String way = "way3"; long startTime = System.currentTimeMillis(); CountDownLatch latch = new CountDownLatch(10); Map<Integer, Integer> map = new ConcurrentHashMap<>(); // 1.10集体 for (int outUser = 1; outUser < 11; outUser++) { AtomicInteger atomicI = new AtomicInteger(outUser); Thread thread = new Thread(() -> { try { int innerUser = atomicI.get(); int lastInnerUser = innerUser - 1; // 2.30张牌 for (int j = 1; j < 31; j++) { // 3.翻牌的速度不能超过前1集体,第1集体例外 Integer lastInnerUserNode = 0; while (innerUser != 1 && ((lastInnerUserNode = map.get(lastInnerUser)) == null || lastInnerUserNode < j)) { } node(way, atomicI, j); map.put(innerUser, j); } } catch (Exception e) { LOGGER.error("Current Thread: " + Thread.currentThread().getName() + "+, exception: ", e); } finally { latch.countDown(); } }, "thread-user-" + outUser); thread.start(); } try { latch.await(); } catch (InterruptedException e) { LOGGER.error("wait thread exception: ", e); } long endTime = System.currentTimeMillis(); return endTime - startTime; } /** * 执行节点 * @param atomicI 第i集体 * @param j 第j张牌 */ private static void node(String way, AtomicInteger atomicI, int j) { int i = atomicI.get(); long currentTime = System.currentTimeMillis() / 1000;// System.out.printf("[%s] %s i-j: %d-%d %d\n", Thread.currentThread().getName(), way, i, j, currentTime); try { if ((i >= 1 && i <= 5 && j >= 1 && j <= 5 && i + j <= 6) || (i >= 6 && i <= 10 && j >= 1 && j <= 5 && i + j <= 11)) { Thread.sleep(1000); } else if ((i >= 1 && i <= 5 && j >= 1 && j <= 5 && i + j > 6) || (i >= 6 && i <= 10 && j >= 1 && j <= 5 && i + j > 11)) { Thread.sleep(1000); } else if (j >= 6) { Thread.sleep(1000); } } catch (Exception e) { LOGGER.error("node sleep exception: ", e); } }}
日志输入:
17:52:10.645 [main] INFO com.peng.java_study.practice.zhikan.AgileTest - time1: 302746 ms17:52:10.648 [main] INFO com.peng.java_study.practice.zhikan.AgileTest - time2: 75632 ms17:52:10.648 [main] INFO com.peng.java_study.practice.zhikan.AgileTest - time3: 39348 ms
从日志中能够看出,理论后果与预期基本一致,多进去的几百毫秒是程序在运行过程中不可避免的耗费。由它们耗时可知:T3 < T2 < T1,所以在不思考其余因素影响的前提下,计划3是最麻利的!
深刻思考
在任何条件下,计划3都实用吗?
答案是否定的,在某些非凡状况下,计划3反而更慢!
假如:
第n - 1集体翻完1 ~ 30张牌后,一起交接给第n集体的筹备工夫和沟通工夫为a。那么最终耗时为:T1’= T1 + (10 - 1) * a =T1 + 9a
若第n - 1集体翻完第1 ~ 5张牌后,一起交接给第n集体时,须要筹备工夫和沟通工夫为b;第n - 1集体翻完第6 ~ 30张牌中的任意一张牌后,交接给第n集体时,须要的筹备工夫与沟通工夫c。那么最终耗时为:T2’= T2 + (10 - 1) b + 25 9 * c =T2 + 9b + 225c
第n - 1集体翻完1 ~ 30张牌中的任意一张牌后,交接给第n集体时,须要的筹备工夫与沟通工夫为d。那么最终耗时为:T3’= T_3 + 30 9 d = T3 + 270d
当初,咱们来验算一遍:
当「筹备工夫与沟通工夫」与「单个工作的执行工夫时」的大小满足肯定的条件时,计划3是否有可能比计划1慢?
假如T3’ > T1’,那么:
T3 + 270d > T1 + 9a 即 10x + 4y + 25z + 270d > 30x + 20y + 250z + 9a
再次假如 x = y = z = 1s,那么上式就等同于:
10 + 4 + 25 + 270d > 30 + 20 + 250 + 9a 即
d > (261 + 9a) / 270或a < (270d - 261) / 9
如果 d = 1s,那 a < 1s 就能够使计划1快于计划3…
由此能够得出结论:在肯定条件下,计划3未必是最优的,且这种状况很有可能产生…
最终论断
在大多数状况下,计划3会比计划1更麻利,但在上述两大节中的非凡状况下,计划3反而是最慢的。因而在实在的生存场景中,还是要“就地取材”,不能一概而论!
思考到这里并没有进行,更多探讨和分享能够期待“麻利小游戏的思考[下]”。
————————————————
LigaAI 新一代智能研发合作平台 让AI 为您的研发团队提供个性化、智能化的我的项目合作体验,化繁就简,帮忙开发者专一、高效的创作。