`
able0001
  • 浏览: 28176 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

[原创]AutoResetEvent, ManualResetEvent的Java模拟

    博客分类:
  • Java
阅读更多

 

AutoResetEvent, ManualResetEvent是C#中常用的线程同步方法,在Java中可以模拟,AutoResetEvent使用Semaphore,增加的是许可证数量,程序里只有一个许可证,那么当这个许可被使用后,就会自动锁定。相反,ManualResetEvent使用countdownlatch,增加的是“latch”,也就是障碍,或者门闩;当障碍解除时,所有程序都可以运行而不被阻塞,如果要实现同步,就必须manual reset,也就是手动加latch。

 

 

 

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class AutoResetEvent
{
    private final Semaphore event;
    private final Integer mutex;

    public AutoResetEvent(boolean signalled)
    {
        event = new Semaphore(signalled ? 1 : 0);
        mutex = new Integer(-1);

    }

    public void set()
    {
        synchronized (mutex)
        {
            if (event.availablePermits() == 0)
            {
                event.release();
            }
        }
    }

    public void reset()
    {
        event.drainPermits();
    }

    public void waitOne() throws InterruptedException
    {
        event.acquire();
    }

    public boolean waitOne(int timeout, TimeUnit unit) throws InterruptedException
    {
        return event.tryAcquire(timeout, unit);
    }

    public boolean isSignalled()
    {
        return event.availablePermits() > 0;
    }

    public boolean waitOne(int timeout) throws InterruptedException
    {
        return waitOne(timeout, TimeUnit.MILLISECONDS);
    }
}

 

 

AutoResetEvent在MSDN中的例子程序在http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx

 

我们可以改写一个java版本,用的是java版本的AutoResetEvent

 

import java.util.Date;
import java.util.Random;

class TermInfo
{
    public long[] terms;
    public int order;
    public long baseValue;
    public AutoResetEvent trigger;
}

public class AutoResetEventTest
{
    private final static int numTerms = 3;

    public static void main(String[] args0) throws InterruptedException
    {
        AutoResetEvent trigger = new AutoResetEvent(false);
        TermInfo tinfo = new TermInfo();
        Thread termThread;
        long[] terms = new long[numTerms];
        int result = 0;

        tinfo.terms = terms;
        tinfo.trigger = trigger;

        for (int i = 0; i < numTerms; i++)
        {
            tinfo.order = i;
            // Create and start the term calc thread.
            TermThreadProc termThreadProc = new TermThreadProc(tinfo);
            termThread = new Thread(termThreadProc);
            termThread.start();
            // simulate a number crunching delay
            Thread.sleep(1000);
            Date date = new Date();
            tinfo.baseValue = Integer.parseInt(String.valueOf((date.getTime())).substring(10));
            trigger.set();
            termThread.join();
            result += terms[i];
        }

        System.out.format("Result = %d", result);
        System.out.println();
    }
}

class TermThreadProc implements Runnable
{

    public TermInfo termInfo;

    public TermThreadProc(TermInfo termInfo)
    {
        this.termInfo = termInfo;
    }

    @Override
    public void run()
    {
        TermInfo tinfo = termInfo;
        System.out.format("Term[%d] is starting...", tinfo.order);
        System.out.println();
        // set the precalculation
        Date date = new Date();
        long preValue = Integer.parseInt(String.valueOf((date.getTime())).substring(10)) + tinfo.order;
        // wait for base value to be ready
        try
        {
            tinfo.trigger.waitOne();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        Random rnd = new Random(tinfo.baseValue);

        tinfo.terms[tinfo.order] = preValue * rnd.nextInt(10000);

        System.out.format("Term[%d] has finished with a value of: %d", tinfo.order, tinfo.terms[tinfo.order]);
        System.out.println();
    }
}
//ManualResetEvent 的Java实现
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class ManualResetEvent
{
    private volatile CountDownLatch event;
    private final Integer mutex;

    public ManualResetEvent(boolean signalled)
    {
        mutex = new Integer(-1);
        if (signalled)
        {
            event = new CountDownLatch(0);
        }
        else
        {
            event = new CountDownLatch(1);
        }
    }

    public void set()
    {
        event.countDown();
    }

    public void reset()
    {
        synchronized (mutex)
        {
            if (event.getCount() == 0)
            {
                event = new CountDownLatch(1);
            }
        }
    }

    public void waitOne() throws InterruptedException
    {
        event.await();
    }

    public boolean waitOne(int timeout, TimeUnit unit) throws InterruptedException
    {
        return event.await(timeout, unit);
    }

    public boolean isSignalled()
    {
        return event.getCount() == 0;
    }

    public boolean waitOne(int timeout) throws InterruptedException
    {
        return waitOne(timeout, TimeUnit.MILLISECONDS);
    }

}


   MSDN地址:http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx

    Java测试:

    
import java.util.Scanner;
import java.io.IOException;

public class ManualResetEventTest
{
    // mre is used to block and release threads manually. It is
    // created in the unsignaled state.
    static AutoResetEvent mre = new AutoResetEvent(false);

    public static void main(String[] arg0) throws IOException, InterruptedException
    {
        System.out.println("\nStart 3 named threads that block on a ManualResetEvent:\n");

        Scanner keyIn = new Scanner(System.in);
        System.out.print("Press the enter key to continue");
        keyIn.nextLine();
        for (int i = 0; i <= 2; i++)
        {
            threadProc threadProc = new threadProc();
            Thread t = new Thread(threadProc);
            t.setName("Thread_" + i);
            t.start();
        }

        Thread.sleep(500);
        System.out.println("\nWhen all three threads have started, press Enter to call Set()"
                + "\nto release all the threads.\n");
        keyIn.nextLine();

        mre.set();

        Thread.sleep(500);
        System.out.println("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()"
                + "\ndo not block. Press Enter to show this.\n");
        keyIn.nextLine();

        for (int i = 3; i <= 4; i++)
        {
            threadProc threadProc = new threadProc();
            Thread t = new Thread(threadProc);
            t.setName("Thread_" + i);
            t.start();
        }

        Thread.sleep(500);
        System.out.println("\nPress Enter to call Reset(), so that threads once again block"
                + "\nwhen they call WaitOne().\n");
        keyIn.nextLine();

        mre.reset();

        // Start a thread that waits on the ManualResetEvent.
        threadProc threadProc = new threadProc();
        Thread t5 = new Thread(threadProc);
        t5.setName("Thread_5");
        t5.start();

        Thread.sleep(500);
        System.out.println("\nPress Enter to call Set() and conclude the demo.");
        keyIn.nextLine();

        mre.set();

    }

}

class threadProc implements Runnable
{

    @Override
    public void run()
    {
        String name = Thread.currentThread().getName();
        System.out.println(name + " starts and calls mre.WaitOne()");

        try
        {
            ManualResetEventTest.mre.waitOne();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        System.out.println(name + " ends.");
    }

}
 

 

0
0
分享到:
评论

相关推荐

    AutoResetEvent_Examples.zip_AutoResetEvent_ManualResetEvent

    在多线程编程中,`AutoResetEvent` 和 `ManualResetEvent` 是两种重要的同步原语,用于控制线程间的协作和同步。本压缩包文件提供了关于这两种事件类型的实例代码,帮助开发者理解它们的工作原理和用法。 首先,让...

    C#-【多线程篇】AutoResetEvent和ManualResetEvent的区别(中级)

    引入命名空间: using System.Threading; AutoResetEvent: autoResetEvent.WaitOne();//运行完后,**自动将事件...ManualResetEvent: manulResetEvent.WaitOne();//运行完后,**不会自动将事件状态设置为无信号**

    ManualResetEvent继续等待.rar

    与AutoResetEvent的区别在于,ManualResetEvent在释放一次后不会自动重置,需要开发者手动调用Reset方法来恢复到未设置状态。 **初始化ManualResetEvent** ManualResetEvent的构造函数允许我们初始化其初始状态。...

    C#线程同步ManualResetEvent

    与`AutoResetEvent`不同,`ManualResetEvent`在释放一次后不会自动重置,需要手动调用`Reset()`方法来恢复未启动状态。 **一、构造函数** `ManualResetEvent`有两个构造函数: 1. `ManualResetEvent(false)`:初始...

    C#线程同步AutoResetEvent

    // 模拟耗时操作 Thread.Sleep(new Random().Next(1000, 3000)); Console.WriteLine($"线程 {threadIndex} 执行完成..."); Interlocked.Increment(ref finishedThreads); // 增加完成线程计数 if ...

    C# 多线程同步、异步_AutoResetEvent用法

    3. **手动重置**:与`ManualResetEvent`不同,`AutoResetEvent`只允许一个线程通过,如果需要多次触发,需要再次调用`Set()`方法。 ### 四、AutoResetEvent的使用 在C#中,我们可以这样使用`AutoResetEvent`: ``...

    python实现AutoResetEvent类的阻塞模式方法解析

    搞过C#多线程的人对其中的AutoResetEvent和ManualResetEvent这两个类都理解,其中的WaitOne()方法和Set()以及Reset()方法在线程同步当中用的是比较多的。 AutoResetEvent :当某个线程执行到WaitOne()方法时,该线程...

    C# 多线程同步与互斥,使用Mutex和AutoResetEvent类

    Mutex(互斥锁)和AutoResetEvent(自动重置事件)是.NET框架提供的两种工具,用于解决这些问题。 Mutex是一种全局资源锁,它允许在任何时间只有一个线程访问特定的资源或代码段。在C#中,我们可以使用Mutex的构造...

    线程同步机制-AutoResetEvent

    AutoResetEvent 允许线程通过发信号互相通信。通常,此通信涉及线程需要独占访问的资源。 线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前...

    autoResetEvent示例

    `AutoResetEvent`是.NET框架提供的一种线程同步机制,用于控制线程间的通信和协调。在本示例中,我们看到“autoResetEvent示例”描述了一个场景:一个线程负责添加任务,而另外三个线程则负责取出任务并进行计算。...

    多线程使用AutoResetEvent

    多线程使用AutoResetEvent

    多线程与网络编程

    本文将重点解析多线程中的线程同步机制,特别是`AutoResetEvent`和`ManualResetEvent`这两种关键同步对象的特性和使用场景。 #### 终止状态与非终止状态:理解线程的生命周期 在多线程编程中,线程的生命周期至关...

    C#使用AutoResetEvent实现同步

    就知道AutoResetEvent这个东西和线程有关,用于处理线程切换之类,于是决定用AutoResetEvent来处理上面的问题。 于是网上查找相关资料: 原来,AutoResetEvent在.Net多线程编程中经常用到。当某个线程调用WaitOne...

    详细解析C#多线程同步事件及等待句柄

    最近捣鼓了一下多线程的同步问题,发现其实C#关于多线程同步事件处理还是很灵活,这里主要写一下,自己测试的一些代码,涉及到了AutoResetEvent 和 ManualResetEvent,当然还有也简要提了一下System.Threading....

    关于线程同步等待的两种代码示例

    在.NET框架中,`ManualResetEvent`和`AutoResetEvent`是两个常用的线程同步工具,它们基于内核对象——事件对象。事件对象可以处于“信号”或“无信号”状态,当线程等待一个无信号的事件时,它会被挂起,直到其他...

    多线程实验_1

    在这个名为“多线程实验_1”的项目中,我们主要探讨了四种关键的多线程操作:AutoResetEvent、ManualResetEvent、Thread.Join()以及委托多线程回调。下面将对这些知识点进行详细的解释和探讨。 首先,`...

    线程间通信与同步控制1

    AutoResetEvent和ManualResetEvent是事件对象,用于线程间的通信和同步,其中AutoResetEvent在释放一个等待线程后自动重置,而ManualResetEvent则需要手动重置。 在设计多线程程序时,应当避免使用Thread.Abort来...

    C# 多线程的同步与互斥(使用Mutex和Event)

    // 模拟耗时操作 for (int i = 0; i ; i++) { } Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} exits the critical section."); mutex.ReleaseMutex(); // 使用AutoResetEvent进行控制...

    C#窗体模拟生产者消费者问题.zip

    5. **事件(Event)**:`AutoResetEvent`和`ManualResetEvent`可以作为线程间通信的信号,当生产者生产完一个产品或者消费者消费完一个产品后,可以通过设置事件来通知对方。 在C#窗体应用中,可能通过按钮控制生产...

Global site tag (gtag.js) - Google Analytics