【JAVA使用笔记】—— 自定义方法的超时控制

本文介绍了Java并发工具箱concurrent包的应用,详细解释了ExecutorService接口的三种实现:Executor、ExecutorService和ScheduledExecutorService,并展示了四种Java线程池的具体用法,同时探讨了Callable和Future在任务执行结果获取中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明

本文介绍的是利用Java 并发工具箱concurrent包,实现对指定类中指定方法的执行时间的控制。

存在于 java.util.concurrent 包里的 ExecutorService 实现就是一个线程池的实现,包里定义了三个Executor接口:

        a. Executor:一个运行新任务的简单接口。

        b. ExecutorService:扩展了Executor接口。添加了一些用来管理执行器生命周期和任务生命周期的方法。

        c. ScheduledExecutorService:扩展了ExecutorService。支持Future和定期执行任务。

Java的线程池有四种:

        a. newCachedThreadPool —— 可缓存线程池,若线程池长度超过处理需要,则回收空线程,否则创建新线程,线程规模可无限大。且若当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

        b. newFixedThreadPool —— 定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

// t_num 最大线程数
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(t_num);

        c. newScheduledThreadPool —— 定长线程池,支持定时的及周期性的任务执行,类似Timer。

// t_num 最大线程数(int)
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(t_num);

// 第一个参数是一个Runnable
// time_delay 延时时间(int)
// time_cycle 执行周期时间(int)
// 最后一个就是时间单位啦
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        // 执行方法
    }
}, time_delay, time_cycle, TimeUnit.xxx);

// 意思就是延迟time_delay秒后每time_cycle秒执行一次。

        d.   newSingleThreadExecutor —— 单线程 的线程池,支持FIFO, LIFO, 优先级策略。

 

接下来需要说明的就是Callable和Future

创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。在线程池提交Callable任务后返回了一个Future对象,使用它可以知道Callable任务的状态和得到Callable返回的执行结果。Future提供了get()方法让我们可以等待Callable结束并获取它的执行结果。

 

代码

public class TimeOutUtil {
    private long timeout;        // 超时时间
    private ExecutorService exec;
    private Callable call;
    private Future future;

    // 构造方法,我们需要初始化超时时间和最大线程数
    public TimeOutUtil(long timeout,int nMethod) {
        this.timeout = timeout;
        this.exec = Executors.newFixedThreadPool(nMethod);
    }

    // 监控方法
    // 参数(指定方法,指定类,方法的参数)
    // 返回方法执行的结果“正常结果”或“超时”或“其他异常”
    public Object checkTimeOut(Method method, Object theObj,Object param){
        System.out.println("LOG : get method "+method.getName());
        try {
            this.call = new Callable() {
                @Override
                public Object call() throws Exception {
                    if(null != param) {
                        return method.invoke(theObj, param);
                    }
                    else
                        return method.invoke(theObj,null);
                }
            };
            this.future = this.exec.submit(this.call);
            Object result = future.get(this.timeout, TimeUnit.MILLISECONDS);

            // 这里做了一下处理,如果方法是一个void就变成Boolean
            if(method.getReturnType() == void.class)
                return true;
            return result;
        } catch (TimeoutException e){
            System.out.println("ERROR : TimeOut");
            if(method.getReturnType() == Boolean.class||
                    method.getReturnType() == void.class)
                return false;
            else return null;
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }

    }

    // 关闭
    public void shutdown(){
        if(!this.exec.isShutdown())
            this.exec.shutdown();
    }
}

使用

// 初始化
TimeOutUtil timeOutUtil = new TimeOutUtil(timeout,t_num);

// T 方法返回类型
// TheClass 指定类
// methodName 方法名
// params_type 方法参数类型
// params 方法参数
T rel =  (T)timeOutUtil
            .checkTimeOut(TheClass.class.getMethod(methodName,params_type),
                          this,
                          params);

// 别忘了关
timeOutUtil.shutdown();

 

### 黑马点评中 Redis 的使用方式与存储方案 #### 一、Redis 在黑马点评中的主要用途 Redis 被广泛应用于高性能缓存场景,其在黑马点评中的核心作用在于提升系统的响应速度并减轻数据库的压力。通过将热点数据加载至内存中,可以显著减少对底层关系型数据库的访问频率。 具体来说,在引用的内容中提到,Redis 不仅用于缓存店铺信息[^1],还被用来存储秒杀活动的优惠券库存数量[^2]。这些功能体现了 Redis 高效的数据处理能力和分布式架构的支持能力。 #### 二、Redis 缓存的具体实现细节 以下是基于提供的代码片段分析得出的一些关键点: 1. **店铺信息缓存** - 方法 `saveShopToRedis` 将店铺对象及其逻辑过期时间封装成一个自定义实体类 `RedisData` 并序列化为 JSON 字符串后存储到 Redis 中。 - 过期策略采用的是逻辑删除而非物理删除,即记录具体的失效时间戳以便后续校验是否已超时。 ```java public void saveShopToRedis(Long id, Long expireSeconds) throws InterruptedException { // 查询店铺数据 Shop shop = getById(id); // 模拟重建缓存延迟 Thread.sleep(200); // 封装逻辑过期时间 RedisData redisData = new RedisData(); redisData.setData(shop); redisData.setExpireTime(LocalDateTime.now().plusSeconds(expireSeconds)); // 写入 Redis stringRedisTemplate.opsForValue() .set(CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(redisData)); } ``` 2. **优惠券库存管理** - 对于秒杀活动中涉及的大规模并发请求,直接操作 MySQL 可能会带来性能瓶颈。因此引入 Redis 来维护每种优惠券剩余可领取的数量,并利用原子减法指令完成扣减动作以保障一致性。 #### 三、Spring Boot 整合 Redis 的配置示例 为了更好地支持上述业务需求,项目通常会在 application.yml 文件里指定连接参数以及线程池大小等相关选项[^3]: ```yaml spring: redis: host: 192.168.1.107 port: 6379 password: 123456 lettuce: pool: max-active: 8 max-idle: 8 min-idle: 0 max-wait: 100 ``` 此外还需注意设置合适的 key 和 value 序列化机制来兼容不同类型的 Java Bean 结构体转换过程. #### 四、探店笔记相关表结构简介 除了基础的商品详情页外,“探店笔记”也是该平台的重要组成部分之一。它允许用户分享自己的实地体验经历并通过评论互动形成社区氛围[^4]. 对应的数据模型由两张表格构成: - 表名:tb_blog 字段描述:包括但不限于标题(title),正文(content), 图片链接(image_url)等等... - 表名:tb_blog_comments 字段描述:关联所属文章ID(post_id),作者(user_name),留言内容(comment_text) 虽然这部分未提及如何运用 Redis 加速此类非交易性质的信息检索流程,但从行业惯例推测应该也会采取相似的技术路线图——即将频繁访问的部分预加载进内存从而加快页面渲染速率. --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值