【问题标题】:a simple multithreaded alarm clock一个简单的多线程闹钟
【发布时间】:2012-10-13 16:57:49
【问题描述】:

我目前正在学习多线程编程,并且很难掌握线程之间的共享资源。

我有两个共享资源,timealarm

我有三个线程,一个每秒不断更新time,一个监视timealarm,最后一个根据用户请求更改timealarm

这是使用互斥信号量来完成的,我有一个简单的设置,描述如下:

  1. Main线程,程序从这里开始,承载timealarm公共变量并实例化子线程。
  2. Tick子线程,每1000ms休眠一次,然后修改Mother线程的time变量
  3. UserInput 子线程,在捕获到用户输入之前被阻塞,并在 Main 线程中修改 timealarm
  4. Alarm 子线程,每 1000ms 休眠一次,当 alarm == time 时关闭

Main 线程为每个资源保留一个互斥锁,因此一次只有一个线程可以访问它。

这样的设计合理还是我把事情复杂化了?

【问题讨论】:

    标签: java multithreading concurrency semaphore


    【解决方案1】:

    我的第一条评论是关于您使用的语言,这可能表明您存在一些误解。线程不拥有任何变量;这可能意味着您已经声明了Thread 的几个自定义子类。如果是这样,这将不是一个可取的方法。请注意,Thread 只是一个类的名称,它不是实际的线程——就像File 不是文件一样。你还没有发布任何代码,所以我必须求助于猜测,但如果我描述的是真的,那么你应该重新设计。使用普通类(不子类化任何东西)并用Runnable 实例化Thread

    其次,“互斥锁”的含义不是很清楚,因为这不是 Java 语言规范定义的术语。如果您指的是 java.util.concurrent 包中的某些内容,例如 Semaphore,这将是矫枉过正;如果您只是指用作锁的普通 Java Object 实例,那将是一种简单直接的方法。但是请注意,您根本不需要任何锁定:volatile 变量就足够了,或者最多使用 AtomicLongs(或您使用的任何类型)来处理两个时间戳值,因此您可以更新它们是原子的。

    【讨论】:

    • 感谢您的澄清! Mutex 是我的教授已经提供的自定义二进制信号量包,它的功能与听起来完全一样。是的,所有线程都是从Thread 类扩展的自定义类。对于子线程,你是说我应该创建匿名 Runnable 类吗?如果我要使用 Runnable 匿名对象,如何通过整个锁定机制从主对象传递共享资源?
    • 匿名类实例可以访问拥有创建它的方法的对象的所有属性,以及范围内的所有final局部变量。这应该足以通过所有必要的。
    • 顺便说一句,我真的很想知道为什么您需要一个完整的自定义二进制信号量包来重新实现内置的 Java 功能。
    • 谢谢!这正是我想要的!一个匿名的可运行文件让事情变得简单了一百万倍!至于自定义 Semaphore,我相信这是因为它将是一个嵌入式程序,教授希望避免与 Oracle 可能存在的法律问题。不太清楚确切的原因,我只知道我们必须使用他的包。
    • 给感兴趣的学生的说明:如果这是您正在设计的嵌入式系统,您可能应该节省系统资源,在这种情况下是线程。您的主线程没有做任何有用的事情,您是否需要一个单独的线程来处理警报是值得怀疑的。此外,设计的滴答线程会导致时钟漂移,因为它与系统时钟不同步。如果您制定了一个定期检查系统时钟的方案,您还可以重用相同的线程来处理警报(除非处理很耗时,但我对此表示怀疑)。
    【解决方案2】:

    我想你可以简单地使用ScheduledExecutorService

    这是一个类,其方法将 ScheduledExecutorService 设置为每隔十秒发出蜂鸣声,持续一小时:

    import static java.util.concurrent.TimeUnit.*;
    class BeeperControl {
    private final ScheduledExecutorService scheduler = 
       Executors.newScheduledThreadPool(1);
    
    public void beepForAnHour() {
        final Runnable beeper = new Runnable() {
                public void run() { System.out.println("beep"); }
            };
        final ScheduledFuture<?> beeperHandle = 
            scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
        scheduler.schedule(new Runnable() {
                public void run() { beeperHandle.cancel(true); }
            }, 60 * 60, SECONDS);
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-08
      相关资源
      最近更新 更多