理解多线程中的ManualResetEvent(C#)
这里你可以看到在同一个类中定义的起点函数。
using System;
using System.Threading;
namespace ThreadingTester
{
class ThreadClass
{
public static void trmain()
{
for (int x = 0; x < 10; x++)
{
Thread.Sleep(1000);
Console.WriteLine(x);
}
}
static void Main(string[] args)
{
Thread thrd1 = new Thread(new ThreadStart(trmain));
thrd1.Start();
for (int x = 0; x < 10; x++)
{
Thread.Sleep(900);
Console.WriteLine("Main :" + x);
}
}
}
}
Thread.Sleep(n)方法把“this”线程置于n毫秒的休眠状态。你可以看看这个例子,在主函数我们定义了一个新的线程,其中它的起点是函数trmain(),我们然后包含了Start()方法开始执行。如果你运行这个例子,你就会了解线程间的切换(让CPU从运行一个线程转到另一个线程)让线程几乎同时运行,为了能看哪个线程运行更快我把主线程设置比新线程少100毫秒。
现在,在开始线程前,先给线程命名:
Thread thrd1=new Thread(new ThreadStart(trmain));
thrd1.Name="thread1";
thrd1.Start();
Thread tr = Thread.CurrentThread;
Console.WriteLine(tr.Name);
在完成上面程序后,设想我们不想在一开始新线程就让它马上运行结束,也就是说,我们开启了一个新线程,让它运行,在某个特定的时间点,新线程暂停并等待从主线程(或其他线程)发来的消息。
我们可以这样定义:
public static ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。注意,为了通知或监听同一个线程,所有的其它线程都能访问那个类。
等待线程这样写:
mre.WaitOne();
这将引起等待线程无限期的阻塞并等待类来通知。
发信号的线程应该这样:
mre.Set();
这样类就会被通知,值变成true,等待线程就会停止等待。在通知事件发生后,我们就可以使用下面语句把线程置于基状态:
mre.Reset();
现在让我们在程序执行一下:
using System;
using System.Threading;
namespace ThreadingTester
{
class ThreadClass
{
public static ManualResetEvent mre = new ManualResetEvent(false);
public static void trmain()
{
Thread tr = Thread.CurrentThread;
Console.WriteLine("thread: waiting for an event");
mre.WaitOne();
Console.WriteLine("thread: got an event");
for (int x = 0; x < 10; x++)
{
Thread.Sleep(1000);
Console.WriteLine(tr.Name + ": " + x);
}
}
static void Main(string[] args)
{
Thread thrd1 = new Thread(new ThreadStart(trmain));
thrd1.Name = "thread1";
thrd1.Start();
for (int x = 0; x < 10; x++)
{
Thread.Sleep(900);
Console.WriteLine("Main:" + x);
if (5 == x) mre.Set();
}
while (thrd1.IsAlive)
{
Thread.Sleep(1000);
Console.WriteLine("Main: waiting for thread to stop");
}
Console.ReadLine();
}
}
}
class Program
{
static void Main(string[] args)
{
const int taskNum = 10;
FBNQC[] fbnqc = new FBNQC[taskNum];
ManualResetEvent[] overEvents = new ManualResetEvent[taskNum];
Random fbnqP = new Random();
for (int i = 0; i < taskNum; i++)
{
overEvents[i] = new ManualResetEvent(false);
fbnqc[i] = new FBNQC(fbnqP.Next(20, 40), overEvents[i]);
ThreadPool.QueueUserWorkItem(fbnqc[i].CallBack , i);
}
WaitHandle.WaitAll(overEvents);
for (int i = 0; i < taskNum; i++)
{
Console.WriteLine("Thread{0}'s parameter is {1},result is {2}!", i, fbnqc[i].pFBNQP, fbnqc[i].pFBNQR);
}
Console.ReadLine();
}
}
class FBNQC
{
public int pFBNQP { get { return mFBNQP; } }
public int pFBNQR { get { return mFBNQR; } }
private int mFBNQP;
private int mFBNQR;
ManualResetEvent mOverEvents;
public FBNQC (int oFBNQP,ManualResetEvent oOverEvents)
{
mFBNQP =oFBNQP ;
mOverEvents =oOverEvents ;
}
public int CalculateFBNQ (int oInt)
{
if (oInt <= 1) return oInt;
return CalculateFBNQ(oInt - 1) + CalculateFBNQ(oInt- 2);
}
public void CallBack(object oObj)
{
int threadIndex=(int)oObj ;
Console .WriteLine ("Thead{0} started....",threadIndex );
mFBNQR = CalculateFBNQ(mFBNQP);
Console.WriteLine("Thread{0} has finished!", threadIndex);
mOverEvents.Set();
}
注:
由于每个斐波纳契对象是给予一个半随机的值来进行计算,而且因为十个线程中的每一个线程将竞争处理机时间,没有办法提前知道要花多少时间才能计算出所有十个结果。那就是为什么在构造期间每个斐波纳契对象被传递一个ManualResetEvent类的实例。每个对象在完成计算之后发信号给提供了的事件对象,该事件对象允许主线程用WaitAll阻塞执行直到所有十个斐波纳契对象都计算完成,Main 方法接显示每个斐波纳契的结果。
理解多线程中的ManualResetEvent(C#)的更多相关文章
- python多线程中join()的理解
在 Python 的多线程编程中,经常碰到 thread.join()这样的代码.那么今天咱们用实际代码来解释一下 join 函数的作用. 第一,当一个进程启动之后,会默认产生一个主线程,因为线程是程 ...
- 深入理解JDK中的I/O
深入理解JDK中的I/O 目 录 java内存模型GCHTTP协议事务隔离级并发多线程设计模式清楚redis.memcache并且知道区别mysql分表分库有接口幂等性了解jdk8稍微了解一下特性 j ...
- 深入理解java中的synchronized关键字
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...
- [译]线程生命周期-理解Java中的线程状态
线程生命周期-理解Java中的线程状态 在多线程编程环境下,理解线程生命周期和线程状态非常重要. 在上一篇教程中,我们已经学习了如何创建java线程:实现Runnable接口或者成为Thread的子类 ...
- c#语言-多线程中的锁系统(一)
介绍 平常在多线程开发中,总避免不了线程同步.本篇就对net多线程中的锁系统做个简单描述. 目录 一:lock.Monitor 1:基础. 2: 作用域. ...
- Java多线程中线程间的通信
一.使用while方式来实现线程之间的通信 package com.ietree.multithread.sync; import java.util.ArrayList; import java.u ...
- 深入理解Java中的不可变对象
深入理解Java中的不可变对象 不可变对象想必大部分朋友都不陌生,大家在平时写代码的过程中100%会使用到不可变对象,比如最常见的String对象.包装器对象等,那么到底为何Java语言要这么设计,真 ...
- Java Volatile关键字 以及long,double在多线程中的应用
概念: volatile关键字,官方解释:volatile可以保证可见性.顺序性.一致性. 可见性:volatile修饰的对象在加载时会告知JVM,对象在CPU的缓存上对多个线程是同时可见的. 顺序性 ...
- 深入理解Java中的同步静态方法和synchronized(class)代码块的类锁
一.回顾学习内容 在前面几篇博客中我我们已经理解了synchronized对象锁.对象锁的重入.synchronized方法块.synchronized非本对象的代码块, 链接:https://www ...
随机推荐
- MySQL具体解释(14)----------事务处理
前言:前一篇文章关于事务处理的博文没有写清楚,读起来非常晦涩.非常难理解,所以有整理了一些资料,帮助理解.见谅! 关于MySQL事务处理学习记 START TRANSACTION COMMIT ROL ...
- Cocos2d-x中Vector<T>容器以及实例介绍
Vector<T> 是Cocos2d-x 3.x推出的列表容器,因此它所能容纳的是Ref及子类所创建的对象指针,其中的T是模板,表示能够放入到容器中的类型,在Cocos2d-x 3.x中T ...
- SQLServer理解copyonly备份操作
Always在添加数据库的过程中如果同步首选项选择的是“完整”,那么就会在主副本上执行copyonly的完整备份和日志备份在辅助副本上执行还原操作,也正是这个操作让我对copyonly有了新的理解.接 ...
- php程序执行过程--非宏观和微观而是写的程序一行一行的路径----利用xdebug了解一段程序的执行过程----覆盖率
1.xdebug_start_code_coverage();//在需要开始跟踪程序执行路径时使用 2.var_dump(xdebug_get_code_coverage());//在结尾使用打印程序 ...
- Spring Data JPA 事务锁
1.概述 在本快速教程中,我们将讨论在Spring Data JPA中为自定义查询方法和预定义存储库的CRUD方法启用事务锁, 我们还将查看不同的锁类型并设置事务锁超时. 2.锁类型 JPA定义了两种 ...
- webStorm 多列编辑
webStorm可以像Sublime一样使用列编辑,只是区别在于webStorm只可以编辑连续列表. 按住alt键鼠标选择一列,然后输入文字就会编辑多行,这个功能很赞,比较实用(按住ALT键选中之后, ...
- 你的JVM还好吗?GC初步诊断
你的JVM还好吗?GC初步诊断 阿飞的博客 JVM的GC机制绝对是很多程序员的福音,它让Java程序员省去了自己回收垃圾的烦恼.从而可以把大部分时间专注业务身上,大大提高了业务开发速度,让产品 ...
- MongoDB的选举过程(转)
转自:http://www.mongoing.com/archives/295 MongoDB的复制集具有自动容忍部分节点宕机的功能,在复制集出现问题时时,会触发选举相关的过程,完成主从节点自动切换. ...
- python爬虫入门篇
优质爬虫入门源码:https://github.com/lining0806/PythonSpiderNotes Python Spider:https://www.cnblogs.com/wangy ...
- iOS上使用自定义ttf字体
本文转载至 http://blog.csdn.net/allison162004/article/details/38777777 项目中想使用第三方的字体,在stackoverflow上查询解决办法 ...