线程池

一、线程

1继承Java.lang.Thread,覆盖run()方法

public class ThreadTest2 extends Thread {
@Override
public void run(){  }
}
new ThreadTest2().start();

2实现Java.lang.Runnable接口,并实现run()方法。

public class RunnalbleTest2 implements Runnable {
@Override
public void run() {  }
}
RunnalbleTest2 runnalbleTest2 = new RunnalbleTest2();
new Thread(runnalbleTest2).start();

二、线程池Executor

  Executors只是一个工厂类,它所有的方法返回的都是ThreadPoolExecutorScheduledThreadPoolExecutor这两个类的实例,这两个类都继承自ExecutorService

 通过Executors提供四种线程池,如下:

  newSingleThreadExecutor 单线程池,同时只有一个线程在跑。

  newCachedThreadPool 回收型线程池,可以重复利用之前创建过的线程,运行线程最大数是Integer.MAX_VALUE

  newFixedThreadPool 固定大小的线程池,跟回收型线程池类似,只是可以限制同时运行的线程数量,超出的在队列中排队

  newScheduledThreadPool创建一个定长线程池,支持定时及周期性(循环)任务执行。

 

public interface ScheduledExecutorService extends ExecutorService 延迟或定期执行任务。 

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(this.concurrentSize.intValue());  //可以实现循环或延迟任务线程池.

 executorService.scheduleWithFixedDelay(new Runnable(){ run(){System.out.println(“执行的线程任务”); }},0L,30L, TimeUnit.MILLISECONDS);  //相对固定的延迟后,执行某项计划,等执行完了,再延迟指定的时间.

  executorService.scheduleAtFixedRate :以固定的频率来执行某项计划(任务),到时间,它就执行,不管是否执行完。

例如1:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
// 1. 创建线程池对象,设置核心线程和最大线程数为5
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
// 2. 创建Runnable(任务)
Runnable task =new Runnable(){
  public void run() {
     System.out.println(Thread.currentThread().getName() + "--->运行");
  }
};
// 3. 向线程池提交任务
fixedThreadPool.execute(task);

 或者:

 fixedThreadPool.execute(()->{
            try{
                //获取分布式锁,判断是否已经执行
                if(redisUtils.hasKey(RedisKeyConstant.SERVER_LOCK)&& RedisListenerConfig.uuid.equals(redisUtils.get(RedisKeyConstant.SERVER_LOCK))){
                    cardPowerCalcService.cardPowerCalc();
                }else if(!redisUtils.hasKey(RedisKeyConstant.SERVER_LOCK)){
                    redisTemplate.opsForValue().setIfAbsent(RedisKeyConstant.SERVER_LOCK, RedisListenerConfig.uuid,10, TimeUnit.SECONDS);
                }
            }catch (Exception e){
                e.printStackTrace();
                log.error("计算卡电量不足定时任务出错:"+e.toString());
            }
        });

  参考:https://blog.csdn.net/qq_40308101/article/details/105122366


实例:
public class MessageDispatcher {
    private final int CORE_SIZE = Runtime.getRuntime().availableProcessors(); //返回的是可用的计算资源,对于支持超线程的CPU来说,单个物理处理器相当于拥有两个逻辑处理器,能够同时执行两个线程

    private ExecutorService[] executors = new ExecutorService[CORE_SIZE];

    @PostConstruct  //用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化
    public void init() {
        for (int i=0; i<executors.length; i++) {
            ExecutorService executor = Executors.newSingleThreadExecutor(
                    new NamedThreadFactory("message-dispatcher"));
            executors[i] = executor;
        }
    }

    public void addMessageTask(DispatchTask task) {
        // 根据分发id求模映射
        int index = task.getDispatchKey() % executors.length;
        executors[index].submit(task);
        executors[index].shutdown();
    }
}

  三、@Scheduled定时任务

      (cron = "0 0/5 * * * ?") 表示每5分钟执行一次

     每隔5秒执行一次:"*/5 * * * * ?"

    每隔1分钟执行一次:"0 */1 * * * ?"

    每天23点执行一次:"0 0 23 * * ?"

    每天凌晨1点执行一次:"0 0 1 * * ?"

    每月1号凌晨1点执行一次:"0 0 1 1 * ?"

    每月最后一天23点执行一次:"0 0 23 L * ?"

    每周星期天凌晨1点实行一次:"0 0 1 ? * L"

    在26分、29分、33分执行一次:"0 26,29,33 * * * ?"

    每天的0点、13点、18点、21点都执行一次:"0 0 0,13,18,21 * * ?"

    表示在每月的1日的凌晨2点调度任务:"0 0 2 1 * ? *"

    表示周一到周五每天上午10:15执行作业:"0 15 10 ? * MON-FRI"

    表示2002-2006年的每个月的最后一个星期五上午10:15执行:"0 15 10 ? 6L 2002-2006"

spring的定时任务时单线程的,可以使用Spring的@Async注解十分容易的实现多线程的任务执行

posted @ 2021-06-15 17:36  zhangtianhong511  阅读(45)  评论(0)    收藏  举报