JUC TimeUnit深入

本文详细介绍了Java并发包中的TimeUnit类,包括其表示的不同时间单位、转换方法及在sleep、wait等操作中的应用。

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

TimeUnit是什么?

JUC的一部分,表示给定粒度单位的持续时间,并提供实用方法以跨单位进行转换,并在这些单位中执行计时和延迟操作。

包含的时间单位

  • NANOSECONDS:纳秒
  • MICROSECONDS:微秒
  • MILLISECONDS:毫秒
  • SECONDS:秒
  • MINUTES:分
  • HOURS:时
  • DAYS:天

时间单位之间的转化

  • 1000 * NANOSECONDS(纳秒) = 1 * MICROSECONDS(微秒)
  • 1000 * MICROSECONDS(微秒) = 1 * MILLISECONDS(毫秒)
  • 1000 * MILLISECONDS(毫秒) = 1 * SECONDS(秒)
  • 60 * SECONDS(秒) = 1 * MINUTES(分)
  • 60 * MINUTES(分) = 1 * HOURS(时)
  • 24 * HOURS(时) = 1 * DAYS(天)

包含的方法

1. public long convert(long sourceDuration, TimeUnit sourceUnit)

convert源码

  • sourceDuration:指的是需要转化的时间量
  • sourceUnit:指的是需要转化的时间单位

这边的方法在每个枚举中都有相应的实现,最终会将传入的时间转换成方法调用的单位。
例如TimeUnit.SECONDS.convert(1, TimeUnit.HOURS),此方法就是将「1小时」转为以秒为单位,所以结果为3600

2. public long toNanos(long duration)

toNanos源码

  • duration:指的是时间量(单位取决于调用方)

此方法是将duration转为以纳秒为单位的数值。
例如TimeUnit.MICROSECONDS.toNanos(1),将1微秒转为纳秒为单位,所以结果为1000

3. public long toMicros(long duration)

toMicros源码

  • duration:指的是时间量(单位取决于调用方)

此方法是将duration转为以微秒为单位的数值。
例如TimeUnit.MILLISECONDS.toMicros(1),将1毫秒转为微秒为单位,所以结果为1000

4. public long toMillis(long duration)

toMillis源码

  • duration:指的是时间量(单位取决于调用方)

此方法是将duration转为以毫秒为单位的数值。
例如TimeUnit.SECONDS.toMillis(1),将1秒转为微秒为单位,所以结果为1000

5. public long toSeconds(long duration)

toSeconds源码

  • duration:指的是时间量(单位取决于调用方)

此方法是将duration转为以秒为单位的数值。
例如TimeUnit.MINUTES.toSeconds(1),将1分钟转为秒为单位,所以结果为60

6. public long toMinutes(long duration)

toMinutes源码

  • duration:指的是时间量(单位取决于调用方)

此方法是将duration转为以分钟为单位的数值。
例如TimeUnit.HOURS.toMinutes(1),将1小时转为分钟为单位,所以结果为60

7. public long toHours(long duration

toHours源码

  • duration:指的是时间量(单位取决于调用方)

此方法是将duration转为以小时为单位的数值。
例如TimeUnit.DAYS.toHours(1),将1天转为小时为单位,所以结果为24

8. public long toDays(long duration)

toDays源码

  • duration:指的是时间量(单位取决于调用方)

此方法是将duration转为以天为单位的数值。
例如TimeUnit.HOURS.toDays(48),将48小时转为天为单位,所以结果为2

9. abstract int excessNanos(long d, long m)

excessNanos源码

  • d:指的是时间量(单位取决于调用方)
  • m:指的是毫秒数

取得时间量(单位取决于调用方)的纳秒数
使用场景:TimeUnit#timedWait

10. public void timedWait(Object obj, long timeout)

timedWait源码

  • obj:要超时等待的对象
  • timeout:超时时间
timedWait原理(本质上就是Object.wait()):
  1. 获取毫秒数
  2. 获取纳秒数
  3. obj.wait()
    wait源码
    wait源码

等待阻塞时底层调用的是Object.wait,而这个wait的超时时间最小支持ns级。所以在调用的时候取得纳秒数,如果999999>纳秒数>0,那么就多等待1ms。

11. public void timedJoin(Thread thread, long timeout)

timedJoin源码

  • thread:需要join的线程
  • timeout:超时时间

同理timedWait,同样是调用Thread.join(),同样最小支持ns级

join源码

12. public void sleep(long timeout)

sleep源码

  • timeout:超时时间

同理timedWait,同样是调用Thread.join(),同样最小支持ns级
sleep源码

为啥TimeUnit要对sleepwait额外封装呢?

首先来看看如何使用?

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            // do something

            try {
                // 1. 使用TimeUnit睡眠2s
                TimeUnit.SECONDS.sleep(2);
                // 2. 使用Thread.sleep()
                Thread.sleep(2 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

从以上的代码可以很明显地看出,使用TimeUnit的方式会更加的简洁且语义明确。

使用的场景

  1. 所有需要对时间进行单位之间的转化action或者是有使用时间的场景,例如:reentrantLock.tryLock(1, TimeUnit.SECONDS);
  2. sleep()wait()join()相关的操作,使用TimeUnit的封装方法可使得程序更加可读。
<think>好的,我现在需要帮用户解答关于Java JUC并发包在春运抢票场景中的应用实现原理的问题。首先,我得回想一下JUC的关键组件,比如线程池、锁机制、原子类、并发容器和同步工具等。然后,结合春运抢票的高并发场景,分析这些组件如何应用。 用户提到的参考引用中有关于守护线程和异常处理的例子,比如CompletableFuture的异常处理,守护线程的设置,以及Lock接口的使用。这些可能在抢票系统中都有应用。比如,线程池管理请求,Lock处理资源竞争,原子类确保余票数的原子操作,并发队列处理排队请求。 接下来需要考虑具体实现步骤,比如如何设计票务库存,如何处理超卖问题,如何限流,以及如何保证系统的高可用。可能还需要提到分布式环境下的扩展,比如使用Redis分布式锁,但用户的问题集中在JUC,所以重点放在单机层面的并发控制。 另外,用户可能想知道JUC中的哪些类或工具在抢票系统中被频繁使用,比如ReentrantLock代替synchronized,ConcurrentHashMap存储票务信息,Semaphore做限流,CountDownLatch同步操作等。还需要注意线程池的配置参数,比如核心线程数、队列类型,避免资源耗尽。 异常处理和补偿机制也很重要,比如引用[1]中的exceptionally方法处理计算错误,确保某个线程的异常不会导致整个系统崩溃,返回默认值。在抢票中,可能需要在扣款失败时进行重试或回滚。 守护线程的应用可能较少,因为抢票业务线程一般是用户线程,但后台监控或日志线程可能设为守护线程,如引用[2]和[3]中的例子,但需要确认是否相关。 最后,生成相关问题时要围绕JUC组件、高并发设计、锁优化、分布式扩展等方面,帮助用户深入理解。</think>### Java JUC在春运抢票场景中的实现原理 春运抢票场景需要解决**高并发访问**和**资源竞争**问题。Java JUCJava Util Concurrency)提供了一套完整的并发工具包,其核心实现原理可分为以下关键步骤: --- #### 1. **线程池管理请求** 使用`ThreadPoolExecutor`处理用户请求,避免频繁创建/销毁线程的开销。例如: ```java ExecutorService executor = new ThreadPoolExecutor( 50, // 核心线程数 200, // 最大线程数 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000) // 任务队列容量 ); ``` 通过合理配置线程池参数,可应对突发的流量高峰[^1]。 --- #### 2. **锁机制控制资源竞争** - **ReentrantLock实现细粒度锁** 对单张车票加锁,避免超卖问题: ```java private final ReentrantLock lock = new ReentrantLock(); public boolean tryBuyTicket(Ticket ticket) { lock.lock(); try { if (ticket.isAvailable()) { ticket.sell(); return true; } return false; } finally { lock.unlock(); } } ``` 相比`synchronized`,`ReentrantLock`支持公平锁、可中断等待等特性[^2]。 - **分段锁优化性能** 将车次数据分片(如按车厢划分),不同分片使用独立锁,减少竞争。 --- #### 3. **原子类保证库存一致性** 使用`AtomicInteger`维护余票数量,确保原子操作: ```java private AtomicInteger remainingTickets = new AtomicInteger(1000); public boolean decrementTicket() { int current = remainingTickets.get(); while (current > 0 && !remainingTickets.compareAndSet(current, current-1)) { current = remainingTickets.get(); } return current > 0; } ``` 通过CAS(Compare-And-Swap)机制避免锁竞争[^3]。 --- #### 4. **并发容器存储状态** 使用`ConcurrentHashMap`缓存车次信息: ```java ConcurrentHashMap<String, Ticket> ticketCache = new ConcurrentHashMap<>(); ``` 其内部通过分段锁实现高并发读写。 --- #### 5. **限流与排队机制** - **Semaphore控制并发量** 限制同时抢票的请求数量: ```java Semaphore semaphore = new Semaphore(1000); // 每秒允许1000个请求 public void handleRequest() { if (semaphore.tryAcquire()) { // 处理请求 } else { // 返回“系统繁忙” } } ``` - **队列缓冲请求** 使用`LinkedBlockingQueue`暂存未能立即处理的请求。 --- #### 6. **异步处理与回调** 通过`CompletableFuture`实现异步扣款、通知等操作: ```java CompletableFuture.supplyAsync(() -> paymentService.deduct(user, amount), executor) .thenAccept(result -> sendNotification(user)) .exceptionally(ex -> { logger.error("支付失败", ex); return null; }); ``` 异常处理机制可参考引用[^1]中的`.exceptionally()`方法。 --- ### 关键设计要点 1. **库存预热**:提前加载车票数据到内存,减少数据库压力。 2. **熔断降级**:通过Hystrix等工具在系统过载时拒绝部分请求。 3. **分布式扩展**:单机JUC方案可结合Redis分布式锁、ZooKeeper集群协调扩展到多节点。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值