首页 > 其他分享 >并发学习记录16:任务调度线程池

并发学习记录16:任务调度线程池

时间:2022-10-05 20:11:38浏览次数:53  
标签:java log 16 void util 线程 import 任务调度 public

在任务调度池功能加入之前,可以使用java.util.Timer来实现定时功能,Timer的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或者异常会影响到后面的任务。

例子

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j(topic = "ch.ThreadPoolTest06")
public class ThreadPoolTest06 {
    public static void main(String[] args) {
//        method01();
//        method02();
        method03();
    }


    public static void method01() {
        Timer timer = new Timer();
        TimerTask task01 = new TimerTask() {
            @Override
            public void run() {
                log.debug("task 01 running");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        TimerTask task02 = new TimerTask() {
            @Override
            public void run() {
                log.debug("task 02 running");
            }
        };
        log.debug("任务进入规划");
        //预期情况就是任务一执行完之后,任务二才会执行
        timer.schedule(task01, 1000);
        timer.schedule(task02, 1000);
    }

    public static void method02() {
        Timer timer = new Timer();
        TimerTask task01 = new TimerTask() {
            @Override
            public void run() {
                log.debug("task 01 running");
                int i = 1 / 0;
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        TimerTask task02 = new TimerTask() {
            @Override
            public void run() {
                log.debug("task 02 running");
            }
        };
        log.debug("任务进入规划");
        //预期情况就是任务一执行出现异常,那么任务二就不会执行
        timer.schedule(task01, 1000);
        timer.schedule(task02, 1000);
    }

    //预期是同时执行,任务调度线程池在线程数目够的情况下会并发执行,而且一个线程的执行成功与否不会影响另一个线程的执行结果
    public static void method03() {
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(2);
        threadPool.schedule(() -> {
            log.debug("任务一执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }, 1, TimeUnit.SECONDS);
        threadPool.schedule(() -> {
            log.debug("任务二执行");
        }, 1, TimeUnit.SECONDS);
    }
}

任务调度线程池的其他用法

任务调度线程池还可以利用scheduleAtFixedRate来实现定时且周期性的执行某些任务

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j(topic = "ch.ThreadPoolTest07")
public class ThreadPoolTest07 {
    static Runnable task01 = new Runnable() {
        @Override
        public void run() {
            log.debug("执行");
        }
    };
    static Runnable task02 = new Runnable() {
        @Override
        public void run() {
            log.debug("执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    };

    public static void main(String[] args) {
//        method01();
        method02();
    }

    public static void method01() {
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(2);
        //传入的是task01,预期就是准备一秒后开始执行,然后每隔一秒执行一次
        log.debug("准备周期性运行");
        threadPool.scheduleAtFixedRate(task01, 1, 1, TimeUnit.SECONDS);
    }

    public static void method02() {
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(2);
        //传入的是task01,预期就是准备一秒后开始执行,然后每隔两秒执行一次,这是因为任务执行时间大于间隔时间,所以间隔变化了两秒
        log.debug("准备周期性运行");
        threadPool.scheduleAtFixedRate(task02, 1, 1, TimeUnit.SECONDS);
    }
}

整个线程池的线程数固定,当任务数多于线程数时,会放入无界队列排队,任务执行完毕,这些线程也不会被释放,可以用来周期性的执行一些任务。

线程池处理异常的方式

一般有两种方式,第一种是主动的捕捉异常;第二种是使用future获取异常

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

@Slf4j(topic = "ch.ThreadPoolTest08")
public class ThreadPoolTest08 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        method1();
        method2();
    }
    
    //主动捕捉异常
    public static void method1() {
        ExecutorService pool = Executors.newFixedThreadPool(1);
        pool.submit(() -> {
            log.debug("任务一");
            try {
                int i = 1 / 0;
            } catch (Exception e) {
                log.error("error:" + e);
            }
        });
    }

    //使用future获取异常
    public static void method2() throws ExecutionException, InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(1);
        Future<Boolean> result = pool.submit(() -> {
            log.debug("task1");
            int i = 1 / 0;
            return true;
        });
        log.debug("result:{}", result.get());
    }
}

应用之定时任务

假设有一个需求是要在每周一下午五点执行一个任务,如何利用线程池来实现呢?

import lombok.extern.slf4j.Slf4j;

import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

//如何在每周二下午17:00五点定时执行一个任务
@Slf4j(topic = "ch.ThreadPoolTest09")
public class ThreadPoolTest09 {
    static final int beginHour = 20;
    public static void main(String[] args) {
        ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(1);
        //任务
        Runnable task = new Runnable() {
            @Override
            public void run() {
                log.debug("任务执行");
            }
        };
//        初始间隔时间,有两种情况
//        第一种情况是当前时间在周二下午五点之前
//        第二种情况是当前时间在周二下午五点之后
        LocalDateTime now = LocalDateTime.now();
        //返回当周的周二下午五点
        LocalDateTime time = now.withHour(beginHour).withMinute(0).withSecond(0).withNano(0).with(DayOfWeek.WEDNESDAY);
        //在周二下午五点之前的情况
        if (now.compareTo(time) > 0) {
            time = time.plusWeeks(1);
        }
        long initialDelay = Duration.between(now, time).toMillis();
        //一周的时间
        long gap = 1000 * 60 * 60 * 24 * 7;
        scheduledPool.scheduleAtFixedRate(task, initialDelay, gap, TimeUnit.MILLISECONDS);
    }
}

标签:java,log,16,void,util,线程,import,任务调度,public
From: https://www.cnblogs.com/wbstudy/p/16754218.html

相关文章

  • Linux多线程服务端编程 pdf
    高清文字版下载链接:https://pan.baidu.com/s/1Ar0sbiycp70BdNysXfkg2w点击这里获取提取码 ......
  • Codeforces 1660 D
    我是蒟蒻!我是蒟蒻!我是蒟蒻!重要的事情说三遍!传送门传送门点这儿!$\color{white}{哈哈哈!你被骗了!}$$\color{white}{真传送门在上面的感叹号!}$思路嗯?一片空白?最......
  • 推荐一款工具,辅助估算线程池参数
    前言相信接触过并发系统的小伙伴们基本都使用过线程池,或多或少调整过对应的参数。以Java中的经典模型来说,能够配置核心线程数、最大线程数、队列容量等等参数。public......
  • 线程之间的通信
    一、为什么要线程通信?  1.多个线程并发执行时,在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务, 并且我们希望他们有规律的执行,那么多线程......
  • Microsoft Office LTSC 2021 for Macv16.67 beta版mac/win
    近日,微软公司发布了office 2021Standard(预览版),以在组织中运行macOS的设备上进行安装和测试。本站第一时间为您带来office2021forMac商业预览版,Mac版office2021包括W......
  • 【笨方法学python】ex16 - 读写文件
    代码如下:点击查看代码#-*-coding:utf-8--*-#读写文件#close-关闭文件(保存)。#read-读取文件内容,结果可赋值给一个变量。#readline-读取文本文件中的一......
  • Demo16_DoWhile与While的区别
    //DoWhile循环结构特性packagecom.HuanXin.JiBen_JieGou;publicclassDemo08_DoWhile1{publicstaticvoidmain(String[]args){intA=0;while(......
  • 在Ubuntu20.04下基于ceph-deploy部署ceph 16.2.x
    一、环境准备1.1、机器环境条件172.16.88.100/192.168.122.100ceph-deploy.example.localceph-deploy2vcpu4G50G172.16.88.101/192.168.122.101ceph-mon1.exa......
  • 线程控制 fork
    线程控制1.线程控制1.1.并行线程1.2.一些代码示例1.2.1.多个initial并行执行1.2.2.单个initial内串行执行1.2.3.fork...join内并行执行1.2.4.join_any......
  • 线程间同步和通信,event semaphore mailbox
    线程间同步和通信,event semaphore mailbox1.概述2.事件event3.wait_order()4.旗语(semaphore)5.semaphore::get();6.semaphore::try_get()7.信箱mailbox......