先来看看例子:
一辆载西瓜的小货车不幸翻车了,有个人去哄抢(这年头,哎~~~)。假设共10个西瓜,这人每次抢一个西瓜最多花1000ms,当然,他每次抢的时间肯定都不同,所以我们用随机数表示。维护次序者(城管?)2000ms后赶到,随即中断哄抢线程。看这人最后抢到几个西瓜?
import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import static java.lang.System.out; class Looting implements Callable<String> { private int wmQuantities; //西瓜总数 private int milliseconds; //sleep时长的上限 public Looting(int wmQuantities, int milliseconds) { this.wmQuantities = wmQuantities; this.milliseconds = milliseconds; out.println("共" + wmQuantities + "个西瓜"); } @Override public String call() throws Exception { int wmCount = 0; //抢到的西瓜计数 Random random =new Random(); //时长随机数 while(++wmCount <= wmQuantities) { out.println("抢到" + wmCount + "个西瓜..."); Thread.sleep(random.nextInt(milliseconds)); //每次搬抢西瓜所花时间是不同的 } return("本次" + wmQuantities + "个西瓜中,抢了" + (wmCount - 1) + "个。"); } } public class LootWatermelon { public static void main(String[] args) throws Exception, ExecutionException { Looting looting = new Looting(10,1000); ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<String> future = executorService.submit(looting); try { future.get(2000, TimeUnit.MILLISECONDS); //假设维护次序人员2000ms后赶到,中断哄抢线程 out.println("事件正常结束。"); } catch(Exception e) { out.println("事件被中断:" + future.cancel(true)); } executorService.shutdownNow(); //关闭ExecutorService } }
运行结果:
共10个西瓜
抢到1个西瓜...
抢到2个西瓜...
抢到3个西瓜...
抢到4个西瓜...
抢到5个西瓜...
事件被中断:true
如果多几个人来哄抢呢?再来看看另一个增强例子:
如果有张三、李四和王二麻子三个人同时哄抢呢?这时候,维护次序者1000ms后赶到,随即中断哄抢线程。看这仨赖子最后抢到几个西瓜?
import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static java.lang.System.out; public class LootWatermelon2 { private static AtomicInteger wmCount = new AtomicInteger(0); //抢到的西瓜计数,这时候改用原子变量 private static int wmQuantities; //西瓜总数 private static int milliseconds; //sleep时长的上限 public LootWatermelon2(int wmQuantities, int milliseconds) { this.wmQuantities = wmQuantities; this.milliseconds = milliseconds; out.println("共" + wmQuantities + "个西瓜。"); } public static class Looting implements Callable<String> { private String someone; //哄抢者 private int someoneWMQuantities = 0; //每个抢到的西瓜总数 public Looting(String someone) { this.someone = someone; out.println(someone + "加入。"); } @Override public String call() throws Exception { Random random =new Random(); //时长随机数 while(wmCount.incrementAndGet() <= wmQuantities) { someoneWMQuantities++; out.println(someone + "抢到本次的第" + wmCount.get() + "个西瓜...其共抢到" + someoneWMQuantities + "个西瓜。"); Thread.sleep(random.nextInt(milliseconds)); //每次搬抢西瓜所花时间是不同的 } return(someone + "共抢到" + someoneWMQuantities + "个西瓜。"); } } public static void main(String[] args) throws Exception, ExecutionException { LootWatermelon2 lootWatermelon2 = new LootWatermelon2(10,1000); Looting looting1 = new Looting("张三"); Looting looting2 = new Looting("李四"); Looting looting3 = new Looting("王二"); ExecutorService executorService = Executors.newFixedThreadPool(3); Future<String> future1 = executorService.submit(looting1); Future<String> future2 = executorService.submit(looting2); Future<String> future3 = executorService.submit(looting3); try { future1.get(1000, TimeUnit.MILLISECONDS); //假设维护次序人员1000ms后赶到,中断哄抢线程 future2.get(1000, TimeUnit.MILLISECONDS); future3.get(1000, TimeUnit.MILLISECONDS); out.println("事件正常结束。"); } catch(Exception e) { out.println("事件被中断:" + future1.cancel(true)); out.println("事件被中断:" + future2.cancel(true)); out.println("事件被中断:" + future3.cancel(true)); } executorService.shutdownNow(); //关闭ExecutorService out.println(looting1.someone + "共抢到" + looting1.someoneWMQuantities + "个西瓜。"); out.println(looting2.someone + "共抢到" + looting2.someoneWMQuantities + "个西瓜。"); out.println(looting3.someone + "共抢到" + looting3.someoneWMQuantities + "个西瓜。"); out.println("还有" + (wmQuantities - looting1.someoneWMQuantities - looting2.someoneWMQuantities - looting3.someoneWMQuantities) + "个西瓜未被抢走。"); } }
运行结果:
共10个西瓜。
张三加入。
李四加入。
王二加入。
李四抢到本次的第1个西瓜...其共抢到1个西瓜。
张三抢到本次的第2个西瓜...其共抢到1个西瓜。
王二抢到本次的第3个西瓜...其共抢到1个西瓜。
王二抢到本次的第4个西瓜...其共抢到2个西瓜。
王二抢到本次的第5个西瓜...其共抢到3个西瓜。
王二抢到本次的第6个西瓜...其共抢到4个西瓜。
张三抢到本次的第7个西瓜...其共抢到2个西瓜。
李四抢到本次的第8个西瓜...其共抢到2个西瓜。
李四抢到本次的第9个西瓜...其共抢到3个西瓜。
事件被中断:true
事件被中断:true
事件被中断:true
张三共抢到2个西瓜。
李四共抢到3个西瓜。
王二共抢到4个西瓜。
还有1个西瓜未被抢走。
写这段代码蛮有意思的。如果愿意,还可以重构一下会更清晰点。
相关推荐
Java 多线程访问的经典例子,一个个代码 手动敲出,可以加深或理解 多线程访问 线程安全与同步的问题.
在学习java多线程的过程中,用这个例子可以很好的理解java多线程的运行原理,参考《java核心技术上》。
里面包含了几个Java线程学习的例子,程序既简单又能让人很快理解线程的工作原理,是初学者不错的选择
一个小例子,有助于理解多线程的知识,一开始厨师做包子,够一百个则换顾客来吃,顾客吃光了再请厨师来做……简明易懂
很适合多线程方面的知识的提升。能对java多线程基础有很大的帮助,就是书中的例子太少,源码也少,不适合深入理解探索,不过是本好书。
java 线程安全的几个测试小例子,充分的理解JMM中的线程内存模型
Java多线程设计模式,通过对多线程环境的分析,抽象出典型的多线程模型,结合Java编程语言的特性,总结出经典的多线程设计模式,通过本资料的学习,足以让您掌握如何使用JAVA编程技术来解决多线程问题,结合本书实例...
java Runnable线程简单实例。简单实用,可用可参考;多用多理解;线程可用用在很多场景,java程序猿必备技能
时钟控件 学习多线程的一个经典例子 JAVA编写 对于多线程的理解有一定的帮助和参考
自己看着文档一步一步理解敲出来的代码。 代码很简洁,注释非常非常...使用纯 Java 实现的多线程下载。如果再配上数据库或者记录下载的进度。 就可以实现了断点下载了,但是我现在还没弄。 分享出来吧。让大家少走弯路
java多线程机制: 例子 1 public class Example1 { static Lefthand left;static Righthand right; public static void main(String args[]) { left=new Lefthand(); //创建两个线程。 right=new Righthand();...
实现java模拟阻塞队列的例子,该代码包括,阻塞队列实现生产者,消费者。和模拟阻塞队列实现生产者及消费者模式,帮助你更好的理解java多线程
其实,它就是一个容器,用于存放线程的局部变量,我认为应该叫做 ThreadLocalVariable(线程局部变量)才对,真不理解为什么当初 Sun 公司的工程师这样命名。 早在 JDK 1.2 的时代,java.lang.ThreadLocal 就诞生了...
一个理解wait()与notify()的例子,让你更好理解.
请最好使用MyEclipse导入工程,或者直接把src中的java文件拷贝到其他工程也可以使用,对想理解线程池概念的同学有很好的帮助
线程同步的理解,对多线程的探讨和例子讲解
join() 定义在Thread.java中。 join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。这句话可能有点晦涩,我们还是通过例子去理解
面向对象经典讲解 深入浅出, 事例深刻,有助于更进一步了解 java 面向对象
Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...
可以作为NIO socket入门的例子,Reactor模式,重点理解key.attach, jar文件里包含了源代码 1,运行server.bat启动服务器,可以打开编辑,修改端口号 2,运行client.bat启动客户端,可以打开编辑,ip,和端口号 3...