技术开发 频道

关于java.util.concurrent不知的事(二)

  4. ScheduledExecutorServices

  尽管 ExecutorService 接口非常有用,但某些任务仍需要以计划方式执行,比如以确定的时间间隔或在特定时间执行给定的任务。这就是 ScheduledExecutorService 的应用范围,它扩展了 ExecutorService。

  如果您的目标是创建一个每隔 5 秒跳一次的 “心跳” 命令,使用 ScheduledExecutorService 可以轻松实现,如清单 4 所示:

  清单 4. ScheduledExecutorService 模拟心跳

import java.util.concurrent.*;

public class Ping
{
    
public static void main(String[] args)
    {
        ScheduledExecutorService ses
=
            Executors.newScheduledThreadPool(
1);
        Runnable pinger
= new Runnable() {
            
public void run() {
                System.out.println(
"PING!");
            }
        };
        ses.scheduleAtFixedRate(pinger,
5, 5, TimeUnit.SECONDS);
    }
}

  这项功能怎么样?不用过于担心线程,不用过于担心用户希望取消心跳时会发生什么,也不用明确地将线程标记为前台或后台;只需将所有的计划细节留给 ScheduledExecutorService。

  顺便说一下,如果用户希望取消心跳,scheduleAtFixedRate 调用将返回一个 ScheduledFuture 实例,它不仅封装了结果(如果有),还拥有一个 cancel 方法来关闭计划的操作。

  5. Timeout 方法

  为阻塞操作设置一个具体的超时值(以避免死锁)的能力是 java.util.concurrent 库相比起早期并发特性的一大进步,比如监控锁定。

  这些方法几乎总是包含一个 int/TimeUnit 对,指示这些方法应该等待多长时间才释放控制权并将其返回给程序。它需要开发人员执行更多工作 — 如果没有获取锁,您将如何重新获取? — 但结果几乎总是正确的:更少的死锁和更加适合生产的代码。(关于编写生产就绪代码的更多信息,请参见 参考资料 中 Michael Nygard 编写的 Release It!。)

  结束语

  java.util.concurrent 包还包含了其他许多好用的实用程序,它们很好地扩展到了 Collections 之外,尤其是在 .locks 和 .atomic 包中。深入研究,您还将发现一些有用的控制结构,比如 CyclicBarrier 等。

  与 Java 平台的许多其他方面一样,您无需费劲地查找可能非常有用的基础架构代码。在编写多线程代码时,请记住本文讨论的实用程序和 上一篇文章 中讨论的实用程序。

0
相关文章