`
songlei8090
  • 浏览: 37746 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java理解线程的例子

 
阅读更多

先来看看例子:

一辆载西瓜的小货车不幸翻车了,有个人去哄抢(这年头,哎~~~)。假设共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个西瓜未被抢走。
写这段代码蛮有意思的。如果愿意,还可以重构一下会更清晰点。

2
0
分享到:
评论
2 楼 long3ok 2014-10-30  
西瓜有漏抢和同时被多个人抢到的情况
1 楼 houyujiangjun 2014-10-30  
有点意思 

相关推荐

    Java 多线程访问的经典例子.txt

    Java 多线程访问的经典例子,一个个代码 手动敲出,可以加深或理解 多线程访问 线程安全与同步的问题.

    java多线程源码,仅供参考

    在学习java多线程的过程中,用这个例子可以很好的理解java多线程的运行原理,参考《java核心技术上》。

    经典线程例子——Java线程学习指南

    里面包含了几个Java线程学习的例子,程序既简单又能让人很快理解线程的工作原理,是初学者不错的选择

    Java多线程的小例子——吃包子

    一个小例子,有助于理解多线程的知识,一开始厨师做包子,够一百个则换顾客来吃,顾客吃光了再请厨师来做……简明易懂

    java多线程并发实战和源码

    很适合多线程方面的知识的提升。能对java多线程基础有很大的帮助,就是书中的例子太少,源码也少,不适合深入理解探索,不过是本好书。

    java线程安全测试

    java 线程安全的几个测试小例子,充分的理解JMM中的线程内存模型

    Java多线程设计模式(含实例源码)

    Java多线程设计模式,通过对多线程环境的分析,抽象出典型的多线程模型,结合Java编程语言的特性,总结出经典的多线程设计模式,通过本资料的学习,足以让您掌握如何使用JAVA编程技术来解决多线程问题,结合本书实例...

    java线程简单实例.txt

    java Runnable线程简单实例。简单实用,可用可参考;多用多理解;线程可用用在很多场景,java程序猿必备技能

    时钟控件 多线程示例 java

    时钟控件 学习多线程的一个经典例子 JAVA编写 对于多线程的理解有一定的帮助和参考

    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模拟阻塞队列的例子,该代码包括,阻塞队列实现生产者,消费者。和模拟阻塞队列实现生产者及消费者模式,帮助你更好的理解java多线程

    Java多线程编程中ThreadLocal类的用法及深入

    其实,它就是一个容器,用于存放线程的局部变量,我认为应该叫做 ThreadLocalVariable(线程局部变量)才对,真不理解为什么当初 Sun 公司的工程师这样命名。 早在 JDK 1.2 的时代,java.lang.ThreadLocal 就诞生了...

    一个理解wait()与notify()的例子

    一个理解wait()与notify()的例子,让你更好理解.

    java线程池窗体小例子

    请最好使用MyEclipse导入工程,或者直接把src中的java文件拷贝到其他工程也可以使用,对想理解线程池概念的同学有很好的帮助

    线程同步的理解

    线程同步的理解,对多线程的探讨和例子讲解

    Java线程之join_动力节点Java学院整理

    join() 定义在Thread.java中。 join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。这句话可能有点晦涩,我们还是通过例子去理解

    面向对象经典讲解 有助于更进一步理解java对象

    面向对象经典讲解 深入浅出, 事例深刻,有助于更进一步了解 java 面向对象

    java源码包---java 源码 大量 实例

     Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...

    java NIO socket聊天室

    可以作为NIO socket入门的例子,Reactor模式,重点理解key.attach, jar文件里包含了源代码 1,运行server.bat启动服务器,可以打开编辑,修改端口号 2,运行client.bat启动客户端,可以打开编辑,ip,和端口号 3...

Global site tag (gtag.js) - Google Analytics