线程池入门--小练习

   日期:2020-09-06     浏览:90    评论:0    
核心提示:线程池的使用步骤可以归纳总结为五步:1:利用Executors工厂类的静态方法,创建线程池对象;2:编写Runnable或Callable实现类的实例对象;3:利用ExecutorService的submit方法或ScheduledExecutorService的schedule方法提交并执行线程任务4:如果有执行结果,则处理异步执行结果(Future)5:调用shutdown()方法,关闭线程池

商品秒杀

假如某网上商城推出活动新上架10部新手机免费送客户体验,要求所有参与活动的人员在规定的时间同时参与秒杀挣抢,假如有30人同时参与了该活动,请使用线程池模拟这个场景,保证前10人秒杀成功,后20人秒杀失败;
要求:

  1. 使用线程池创建线程
  2. 解决线程安全问题

1:既然商品总数量是10个,那么我们可以在创建线程池的时候初始化线程数是10个及以下,设计线程池最大数量为10个;
2:当某个线程执行完任务之后,可以让其他秒杀的人继续使用该线程参与秒杀;
3:使用synchronized控制线程安全,防止出现错误数据;

  • 任务类:
    包含了商品数量,客户名称,秒杀手机的行为
public class MyTask implements Runnable{
	
    private static int id =10;
    
    private String username;

    public MyTask(String username) {
        this.username = username;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(username+"正在使用"+name+"线程,参与华为P30秒杀活动");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        synchronized (MyTask.class){
            if (id>0){
                System.out.println(username+"使用"+name+"线程,成功秒杀华为P30!!");
                id--;
                if (id>0){
                    System.out.println("商品还剩下"+id+"个");
                }else {
                    System.out.println("商品已售完");
                }
            }else{
                System.out.println(username+"秒杀失败啦!");
            }
        }
    }
}
  • 主程序类,测试任务类
public class MyTest {
    public static void main(String[] args) {
        //创建一个线程池对象(3个核心,最大线程5个,时间1,单位分钟,任务队列长度15)
        ThreadPoolExecutor pool=new ThreadPoolExecutor(5,10, 1, TimeUnit.MINUTES,new LinkedBlockingQueue<>(20));
        //循环创建任务对象
        for (int i=1;i<=30;i++) {
            MyTask myTask = new MyTask("客户"+i);
            pool.submit(myTask);
        }
        //关闭线程池
        pool.shutdown();
    }
}

取款业务

设计一个程序,使用两个线程模拟在两个地点同时从一个账号中取钱,假如卡中一共有1000元,每个线程取800元,要求演示结果一个线程取款成功,剩余200元,另一个线程取款失败,余额不足;

要求:
1. 使用线程池创建线程
2. 解决线程安全问题
提示:
1. 线程池可以利用Executors工厂类的静态方法,创建线程池对象;
2. 解决线程安全问题可以使用synchronized方法控制取钱的操作
3. 在取款前,先判断余额是否足够,且保证余额判断和取钱行为的原子性;
  • 任务类
public class MyTask implements Runnable{
    //用户姓名
    private String username;
    //取款金额
    private double money;
    //总金额
    private static double total =1000;

    public MyTask(String username, double money) {
        this.username = username;
        this.money = money;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(username+"准备取款"+money+"元");
        synchronized (MyTask.class){
            if ((total-money>0)) {
                System.out.println(username + "使用" + name + "线程,取款:" + money + "元");
                total=total-money;
            }else {
                System.out.println(username + "使用" + name + "线程,取款:" + money + "元失败!!!");

            }
        }
    }
}

  • 主程序类,测试任务类
public class MyTest {
    public static void main(String[] args) {
        //创建线程池对象
        ExecutorService pool = Executors.newFixedThreadPool(2, new ThreadFactory() {
            int id =1;
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"ATM"+id++);
            }
        });
        //创建两个任务提交
        for(int i=1;i<=2;i++){
            MyTask myTask =new MyTask("客户"+i, 600);
            pool.submit(myTask);
        }
        //关闭线程池
        pool.shutdown();
    }
}

总结

线程池的使用步骤可以归纳总结为五步:
1:利用Executors工厂类的静态方法,创建线程池对象;
2:编写Runnable或Callable实现类的实例对象;
3:利用ExecutorService的submit方法或ScheduledExecutorService的schedule方
法提交并执行线程任务
4:如果有执行结果,则处理异步执行结果(Future)
5:调用shutdown()方法,关闭线程池

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服