java线程池ThreadPoolExecutor,多并发,抢票实例

背景:最开始处理多并发是使用锁+线程来处理的,现在基本上不直接写线程,更多是使用分布式框架等来解决这些问题。

抢车票这个例题,在老师教线程的时候,一般都是举这个栗子,先用线程,然后发生数据错乱,然后告诉你要用锁来保证数据的正确性等。以下,我使用的是线程池来实现这个栗子,主要是因为最近想多了解了解线程池~

package org.litluecat.utils;

import java.util.concurrent.*;

/**
 * 线程池工具类
 * @author Litluecat
 */
public class ThreadPoolUtils {

    /**
     * 允许同时执行的线程数
     */
    private static Integer corePoolSize = 3;
    /**
     * 允许创建的最大线程数
     */
    private static Integer maximumPoolSize = 50;
    /**
     * 表示线程没有任务执行时最多保持多久时间会终止
     */
    private static Long keepAliveTime = 5000L;
    /**
     * 参数keepAliveTime的时间单位
     * TimeUnit.DAYS;               //天
     * TimeUnit.HOURS;             //小时
     * TimeUnit.MINUTES;           //分钟
     * TimeUnit.SECONDS;           //秒
     * TimeUnit.MILLISECONDS;      //毫秒
     * TimeUnit.MICROSECONDS;      //微妙
     * TimeUnit.NANOSECONDS;       //纳秒
     */
    private static TimeUnit unit = TimeUnit.MILLISECONDS;
    /**
     * 一个阻塞队列策略,用来存储等待执行的任务
     * ArrayBlockingQueue
     * LinkedBlockingQueue 无界队列,就是没有指定容量,可以无限大
     * SynchronousQueue
     * PriorityBlockingQueue
     */
    private static BlockingQueue workQueue = new LinkedBlockingQueue<>(maximumPoolSize);
    /**
     *用于设置创建线程的工厂,比如设置daemon和优先级等
     */
    private static ThreadFactory threadFactory = new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            return thread;
        }
    };
    /**
     * 表示当拒绝处理任务时的策略
     * 1、AbortPolicy:直接抛出异常。
     * 2、CallerRunsPolicy:只用调用者所在线程来运行任务。
     * 3、DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
     * 4、DiscardPolicy:不处理,丢弃掉。
     * 5、也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化不能处理的任务。
     */
    private static RejectedExecutionHandler  handler = new ThreadPoolExecutor.CallerRunsPolicy();
    private static ThreadPoolExecutor threadPoolExecutor = null;

    /**
     * 获取线程池对象
     * @return
     */
    public static ThreadPoolExecutor getThreadPoolExecutor() {
        if (null == threadPoolExecutor) {
            ThreadPoolExecutor t;
            synchronized (ThreadPoolExecutor.class) {
                t = threadPoolExecutor;
                if (null == t) {
                    synchronized (ThreadPoolExecutor.class) {
                        t = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
                    }
                    threadPoolExecutor = t;
                }
            }
        }
        return threadPoolExecutor;
    }

    /**
     * 设置允许同时执行的线程数
     * @param corePoolSize
     */
    public static void setCorePoolSize(int corePoolSize){
        ThreadPoolUtils.corePoolSize = corePoolSize;
    }
    /**
     * 设置阻塞策略
     * @param handler
     */
    public static void setHandler(RejectedExecutionHandler  handler){
        ThreadPoolUtils.handler = handler;
    }
    /**
     * 设置线程工厂对象
     * @param threadFactory
     */
    public static void setThreadFactory(ThreadFactory threadFactory){
        if(null != threadFactory){
            ThreadPoolUtils.threadFactory = threadFactory;
        }else{
            System.out.println("请确认ThreadFactory线程工厂对象不为空");
        }
    }


    public static void main(String[] args){
        int count = 8;
        System.out.println("现有火车票"+count+"张,开始售票:");
        String[] user = {"小华","小明","大名","花花","小花","螺蛳粉","火锅","小酥肉","五花肉","雪花牛肉"};
        try{
            RunnableTest test = new RunnableTest(count,60);
            MyThreadFactory myThreadFactory = new MyThreadFactory();
            ThreadPoolUtils.setThreadFactory(myThreadFactory.get());
            ThreadPoolUtils.setHandler(new RejectedExecutionHandler() {
                @Override
                public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                    System.out.println(r.toString()+"执行了拒绝策略");
                }
            });
            ThreadPoolUtils.setCorePoolSize(user.length);
            ThreadPoolExecutor threadPool = ThreadPoolUtils.getThreadPoolExecutor();

            for(String userName : user){
                myThreadFactory.setUserName(userName);
                threadPool.execute(test);
            }

            Thread.sleep(1000L);
            System.out.println("======================================================================================");
            System.out.println("获取活动的线程数:"+threadPool.getActiveCount());
            System.out.println("线程池需要执行的任务数量:"+threadPool.getTaskCount());
            System.out.println("线程池在运行过程中已完成的任务数量:"+threadPool.getCompletedTaskCount());
            threadPool.shutdown();
            System.out.println("======================================================================================");

            String successUserName = "恭喜以下用户抢到车票:";
            for(String userName : test.getSuccessUserList()){
                successUserName += userName+" ";
            }
            System.out.println(successUserName);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

线程工厂

package org.litluecat.utils;

import java.util.concurrent.ThreadFactory;

/**
 * 线程工厂
 * @author Litluecat
 */
public class MyThreadFactory {

    private String userName;

    public ThreadFactory get(){
        ThreadFactory threadFactory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r,userName);
                return thread;
            }
        };
        return threadFactory;
    }

    public void setUserName(String userName){
        this.userName = userName;
    }
}

线程Runnable

package org.litluecat.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 抢车票
 * @author Litluecat
 */
public class RunnableTest implements Runnable {
    //随机数
    Random r = new Random();
    //抢票成功概率
    int success;
    //总票数
    int count;
    List<String> successUserList = new ArrayList<>();
    public RunnableTest(int count, int success){
        this.count = count;
        this.success = success;
    }

    public List<String> getSuccessUserList(){
        return successUserList;
    }
    @Override
    public void run() {
        try{
            String userName = Thread.currentThread().getName();
            boolean start = successUserList.contains(userName);

            while(!start){
                if (0 < count) {
                    synchronized (this) {
                        if (success < r.nextInt(100) && !start) {
                            count--;
                            System.out.println(userName + ":已抢到:剩余车票:" + (count) + "张");
                            successUserList.add(userName);
                            start = true;
                        } else {
                            System.out.println(userName + ":正在抢票中,请稍后。。。");
                        }
                    }
                }else{
                    System.out.println(userName+":车票已售毕:剩余车票:"+(count)+"张");
                    start = true;
                }
            }
            Thread.sleep(500L);
        } catch (InterruptedException e) {
            System.out.println("线程休眠异常。。。");
        }
    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值