سؤال

ما الذي يجب أن أستخدمه للحصول على دلالات تعادل Autoresetevent. في جاوة؟ (يرى هذا السؤال for manalresetevent).

هل كانت مفيدة؟

المحلول

بدا إجابة user249654 واعدة. أضفت بعض اختبارات الوحدات للتحقق من ذلك، وفي الواقع أنها تعمل كما هو متوقع.

أضفت أيضا الحمل الزائد waitOne التي تأخذ المهلة.

الرمز هنا في حالة العثور على أي شخص آخر مفيدا:

اختبار الوحدة

import org.junit.Assert;
import org.junit.Test;

import static java.lang.System.currentTimeMillis;

/**
 * @author Drew Noakes http://drewnoakes.com
 */
public class AutoResetEventTest
{
    @Test
    public void synchronisesProperly() throws InterruptedException
    {
        final AutoResetEvent event1 = new AutoResetEvent(false);
        final AutoResetEvent event2 = new AutoResetEvent(false);
        final int loopCount = 10;
        final int sleepMillis = 50;

        Thread thread1 = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try {
                    for (int i = 0; i < loopCount; i++)
                    {
                        long t = currentTimeMillis();
                        event1.waitOne();
                        Assert.assertTrue("Time to wait should be within 5ms of sleep time",
                                Math.abs(currentTimeMillis() - t - sleepMillis) < 5);
                        Thread.sleep(sleepMillis);
                        t = currentTimeMillis();
                        event2.set();
                        Assert.assertTrue("Time to set should be within 1ms", currentTimeMillis() - t <= 1);
                    }
                } catch (InterruptedException e) {
                    Assert.fail();
                }
            }
        });

        Thread thread2 = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try {
                    for (int i = 0; i < loopCount; i++)
                    {
                        Thread.sleep(sleepMillis);
                        long t = currentTimeMillis();
                        event1.set();
                        Assert.assertTrue("Time to set should be within 1ms", currentTimeMillis() - t <= 1);
                        t = currentTimeMillis();
                        event2.waitOne();
                        Assert.assertTrue("Time to wait should be within 5ms of sleep time",
                                Math.abs(currentTimeMillis() - t - sleepMillis) < 5);
                    }
                } catch (InterruptedException e) {
                    Assert.fail();
                }
            }
        });

        long t = currentTimeMillis();

        thread1.start();
        thread2.start();

        int maxTimeMillis = loopCount * sleepMillis * 2 * 2;

        thread1.join(maxTimeMillis);
        thread2.join(maxTimeMillis);

        Assert.assertTrue("Thread should not be blocked.", currentTimeMillis() - t < maxTimeMillis);
    }

    @Test
    public void timeout() throws InterruptedException
    {
        AutoResetEvent event = new AutoResetEvent(false);

        int timeoutMillis = 100;
        long t = currentTimeMillis();
        event.waitOne(timeoutMillis);
        long took = currentTimeMillis() - t;
        Assert.assertTrue("Timeout should have occurred, taking within 5ms of the timeout period, but took " + took,
                Math.abs(took - timeoutMillis) < 5);
    }

    @Test
    public void noBlockIfInitiallyOpen() throws InterruptedException
    {
        AutoResetEvent event = new AutoResetEvent(true);

        long t = currentTimeMillis();
        event.waitOne(200);
        Assert.assertTrue("Should not have taken very long to wait when already open",
                Math.abs(currentTimeMillis() - t) < 5);
    }
}

التشغيل التلقائي مع الزائد الذي يقبل مهلة

public class AutoResetEvent
{
    private final Object _monitor = new Object();
    private volatile boolean _isOpen = false;

    public AutoResetEvent(boolean open)
    {
        _isOpen = open;
    }

    public void waitOne() throws InterruptedException
    {
        synchronized (_monitor) {
            while (!_isOpen) {
                _monitor.wait();
            }
            _isOpen = false;
        }
    }

    public void waitOne(long timeout) throws InterruptedException
    {
        synchronized (_monitor) {
            long t = System.currentTimeMillis();
            while (!_isOpen) {
                _monitor.wait(timeout);
                // Check for timeout
                if (System.currentTimeMillis() - t >= timeout)
                    break;
            }
            _isOpen = false;
        }
    }

    public void set()
    {
        synchronized (_monitor) {
            _isOpen = true;
            _monitor.notify();
        }
    }

    public void reset()
    {
        _isOpen = false;
    }
}

نصائح أخرى

class AutoResetEvent {

  private final Object monitor = new Object();
  private volatile boolean open = false;

  public AutoResetEvent(boolean open) {
    this.open = open;
  }

  public void waitOne() throws InterruptedException {
    synchronized (monitor) {
      while (open == false) { 
        monitor.wait();
      }
      open = false; // close for other
    }

  }

  public void set() {
    synchronized (monitor) {
      open = true;
      monitor.notify(); // open one 
    }
  }

  public void reset() {//close stop
    open = false;
  }
}

كنت قادرا على الحصول على سيكليكابارير للعمل لأغراضي.

هنا رمز C # الذي كنت أحاول إعادة إنتاجه في جاوة (إنه مجرد برنامج مظاهرة كتبت لعزل النموذج، فأنا الآن استخدمه في برامج C # أنا أكتب لتوليد الفيديو في الوقت الفعلي، لتوفير سيطرة دقيقة على معدل الإطار) في

using System;
using System.Timers;
using System.Threading;

namespace TimerTest
{
    class Program
    {
        static AutoResetEvent are = new AutoResetEvent(false);
        static void Main(string[] args)
        {
            System.Timers.Timer t = new System.Timers.Timer(1000);
            t.Elapsed += new ElapsedEventHandler(delegate { are.Set(); });
            t.Enabled = true;
            while (true)
            {
                are.WaitOne();
                Console.WriteLine("main");
            }
        }
    }
}

وهنا هو رمز Java الذي توصل إليه للقيام بنفس الشيء (باستخدام فئة Cyclicbarrier كما هو مقترح في إجابة سابقة):

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CyclicBarrier;

public class TimerTest2 {
    static CyclicBarrier cb;

    static class MyTimerTask extends TimerTask {
        private CyclicBarrier cb;
        public MyTimerTask(CyclicBarrier c) { cb = c; }

        public void run() { 
            try { cb.await(); } 
            catch (Exception e) { } 
        }
    }

    public static void main(String[] args) {
        cb = new CyclicBarrier(2);
        Timer t = new Timer();
        t.schedule(new MyTimerTask(cb), 1000, 1000);

        while (true) {
            try { cb.await(); } 
            catch (Exception e) { }
            System.out.println("main");
        }
    }
}

تمديد آخر للحل من الإجابة المقبولة في حال كنت ترغب في معرفة ما إذا كان الانتظار الخاص بك انتهت مع مهلة أو مع مجموعة الأحداث (وهو بالضبط ما يفعله .NET Autoresetevent).

public boolean waitOne(long timeout) throws InterruptedException {
    synchronized (monitor) {
        try {
            long t = System.currentTimeMillis();
            while (!isOpen) {
                monitor.wait(timeout);
                // Check for timeout
                if (System.currentTimeMillis() - t >= timeout)
                    break;
            }

            return isOpen;
        }
        finally {
            isOpen = false;
        }
    }
}
import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

public class AutoResetEvent {

  private volatile boolean _signaled;
  private ReentrantLock _lock;
  private Condition _condition;

  public AutoResetEvent(boolean initialState) {
    _signaled = initialState;
    _lock = new ReentrantLock();
    _condition = _lock.newCondition();
  }

  public void waitOne(long miliSecond) throws InterruptedException {
    _lock.lock();
    try {
      while (!_signaled)
        _condition.await(miliSecond, TimeUnit.MILLISECONDS);
      _signaled = false;
    } finally {
        _lock.unlock();
    }
  }

  public void waitOne() throws InterruptedException {
    _lock.lock();
    try {
      while (!_signaled)
        _condition.await();
      _signaled = false;
    } finally {
        _lock.unlock();
    }
  }

  public void set() {
    _lock.lock();
    try {
      _condition.signal();
      _signaled = true;
    } finally {
      _lock.unlock();
    }
  }

  public void reset() {
    _lock.lock();
    try {
      _signaled = false;
    } finally {
      _lock.unlock();
    }
  }
}

أعتقد أن ما تبحث عنه هو إما cyclicbarrier أو العد البردية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top