浅解多线程(二)之和尚们的那些事儿
浅解多线程(一)之线程入门起步
本文链接
1.确定多线程的结束时间,thread的IsAlive属性
2.线程优先级,thread的ThreadPriority属性
3.线程通信之Monitor类
4.线程排队之Join
5.多线程互斥锁Mutex
6.信号量maphore
确定多线程的结束时间,thread的IsAlive属性
在多个线程运行的背景下,了解线程什么时候结束,什么时候停止是很有必要的。
案例:老和尚念经计时,2本经书,2个和尚念,一人一本,不能撕破,最短时间念
完,问老和尚们念完经书最短需要多长时间。
分析:首先在开始念经的时候给计时,记为A,最后在记下慢和尚念完经书时的时
间,记为B。求B-A
代码:IsAlive属性:标识此线程已启动并且尚未正常终止或中止,则为true,再
念,没念完,努力中;否则为fal,念完啦,歇着。
//和尚1,和尚2
publicThreadtd1,td2;
publicvoidStarThread()
{
//开启一个线程执行Hello方法,即和尚1念菠萝菠萝蜜
ThreadStartts=newThreadStart(Hello);
td1=newThread(ts);
();
}
publicvoidStarThread1()
{
//开启一个线程执行Welcome方法,即和尚2念大金刚经
ThreadStartts=newThreadStart(Welcome);
td2=newThread(ts);
();
}
publicstringsayh="",sayw="";
//菠萝菠萝蜜
publicvoidHello()
{
//念
sayh="Helloweveryone!";
}
//大金刚经
publicvoidWelcome()
{
//念
sayw="WelcometoShangHai!";
//偷懒10秒
(10000);
}
protectedvoidbtn_StarThread_Click(objectnder,EventArg)
{
//记时开始,预备念
("开始念的时间:"+ng()+"");
//和尚1就位
StarThread();
//和尚2就位
StarThread1();
inti=0;
while(i==0)
{
//判断线程的IsAlive属性
//IsAlive标识此线程已启动并且尚未正常终止或中止,则为
true;否则为fal。
//如果两个都为fal说明,线程结束终止
if(!e&&!e)
{
i++;
if(i==1)
{
//念得内容,绕梁三尺。
("我们年的内容:"+(sayh+"+"+sayw)+"");
("念完时的时间:"+ng());
();
}
}
}
}
线程优先级,thread的ThreadPriority属性
线程优先级区别于线程占有cpu时间的多少,当然优先级越高同等条件下占有的cpu
时间越多。级别高的执行效率要高于级别低的。
优先级有5个级别:Lowest
Normal。
案例:老和尚娶媳妇。佛祖说:你们3个和尚,清修刻苦,现特许你们娶媳妇啦,
不过娶媳妇的只能是你们三个中间的一人。条件是我手中的经书谁能先念完,谁可
以娶。
分析:和尚平时都很刻苦,各有特点,平时和尚1在lowest环境下念经,和尚2
在normal环境下念经,和尚3在Highest环境下念经。
protectedvoidbtn_StarThread_Click(objectnder,EventArg)
{
Write();
}
//i为和尚1念的页数
//j为和尚2念的页数
//k为和尚3念的页数
//c为经书总页数
inti=0,j=0,k=0,c=10000000;
//和尚1念经
publicvoidJsi()
{
while(i<=c)
{
i+=1;
}
}
//和尚2念经
publicvoidJsj()
{
while(j<=c)
{
j+=1;
}
}
//和尚3念经
publicvoidJsk()
{
while(k<=c)
{
k+=1;
}
}
publicvoidWrite()
{
//开启线程计算i
ThreadStartsti=newThreadStart(Jsi);
Threadtdi=newThread(sti);
//设置线程优先级为Lowest。和尚1在Lowest环境下念经
ty=;
//开启线程计算j
ThreadStartstj=newThreadStart(Jsj);
Threadtdj=newThread(stj);
//设置线程优先级为Normal。和尚2在Normal环境下念经
ty=;
//开启线程计算k
ThreadStartstk=newThreadStart(Jsk);
Threadtdk=newThread(stk);
//设置线程优先级为Highest。和尚3在Highest环境下念经
ty=t;
//开始
();
();
();
ints=0;
while(s==0)
{
if(k>c)
{
s++;
("比赛结束,结果如下:");
("和尚1在Lowest环境下念经:"+i+"页和尚2在Normal
环境下念经:"+j+"页和尚3在Highest环境下念经:"+k+"页
");
("佛祖又说:你念或者不念,苍老师,就在那里!");
();
}
}
}
为啦方便期间,从这以后,我要用控制台程序演示,操控线程。
线程通信之Monitor类
如果,你的线程A中运行锁内方法时候,需要去访问一个暂不可用资源B,可能在B
上需耗费很长的等待时间,那么这时候你的线程A,将占用锁内资源,阻塞其它线
程访问锁定内容,造成性能损失。你该怎么解决这样子的问题呢?这样,让A暂时
放弃锁,停留在锁中的,允许其它线程访问锁,而等B资源可用时,通知A让他继
续锁内的操作。是不是解决啦问题,这样就用到啦这段中的Monitor类,提供的几
个方法:Wait(),Pul(),PulAll(),这几个方法只能在当前锁定中使用。
Wait():暂时中断运行锁定中线程操作,释放锁,时刻等待着通知复活。
Pul():通知等待该锁线程队列中的第一个线程,此锁可用。
PulAll():通知所有锁,此锁可用。
案例:嵩山少林和尚开会。主持人和尚主持会议会不停的上舞台讲话,方丈会出来
宣布大会开始,弟子们开始讨论峨眉山怎么走。
分析:主持人一个线程,方丈一个线程,弟子们一个线程,主持人贯彻全场。
publicclassMutexSample
{
staticvoidMain()
{
commcom=newcomm();
ads();
y();
}
}
publicclasscomm
{
//状态值:0时主持人和尚说,1时方丈说,2时弟子们说,3结束。
intsayFla;
//主持人上台
inti=0;
publicvoidzcrSay()
{
lock(this)
{
stringsayStr;
if(i==0)
{
//让方丈说话
sayFla=1;
sayStr=+"今晚,阳光明媚,多云转晴,方丈大师,
程祥云而来,传扬峨眉一隅,情况如何,还请方丈闪亮登场。";
ine(sayStr);
i++;
//此时sayFla=1通知等待的方丈线程运行
(this);
//暂时锁定主持人,暂停到这里,释放this让其它线程访问
(this);
}
//被通知后,从上一个锁定开始运行到这里
if(i==1)
{
//让弟子说话
sayFla=2;
sayStr=+"看方丈那幸福的表情,徜徉肆恣,愿
走的跟他去吧。下面请弟子们各抒己见";
ine(sayStr);
i++;
//此时sayFla=12通知等待的弟子线程运行
(this);
//暂时锁定主持人,暂停到这里,释放this让其它线程访问
(this);
}
//被通知后,从上一个锁定开始运行到这里
if(i==2)
{
sayFla=3;
sayStr=+"大会结束!方丈幸福!!苍老师你在
哪里?!!放开那女孩...";
ine(sayStr);
i++;
(this);
}
}
}
//方丈上台
publicvoidfzSay()
{
lock(this)
{
while(true)
{
if(sayFla!=1)
{
(this);
}
if(sayFla==1)
{
ine(+"蓝蓝的天空,绿绿的湖水,
我看见,咿呀呀呀,看见一老尼,咿呀呀,在水一方。愿意来的一起来,不愿来
的苍老师给你们放寺里。。咿呀呀,我走啦。。。");
//交给主持人
sayFla=0;
//通知主持人线程,this可用
(this);
}
}
}
}
//弟子上台
publicvoiddzSay()
{
lock(this)
{
while(true)
{
if(sayFla!=2)
{
(this);
}
if(sayFla==2)
{
ine(+"果真如此的话,还是方丈
大师自己去吧!!祝福啊....");
//交给主持人
sayFla=0;
(this);
}
}
}
}
publicvoiddhThreads()
{
ThreadzcrTd=newThread(newThreadStart(zcrSay));
ThreadfzTd=newThread(newThreadStart(fzSay));
ThreaddzTd=newThread(newThreadStart(dzSay));
="主持人:";
="方丈:";
="弟子:";
();
();
();
}
}
线程排队之Join
多线程,共享一个资源,先后操作资源。Join()方法,暂停当前线程,直到指定线
程运行完毕,才唤醒当前线程。如果没有Join,多线程随机读取公用资源,没有先
后次序。
案例:两个和尚念一本经书,老和尚年前半本书,小和尚念后半本书,小和尚调皮,
非要先念,就给老和尚用迷魂药啦。。
分析:一本书6页,小和尚4-6,老和尚1-3,两个和尚,两个线程。
publicclass连接线程Join
{
//小和尚
publicstaticThreadlitThread;
//老和尚
publicstaticThreadoldThread;
//老和尚念经
staticvoidoldRead()
{
//老和尚被小和尚下药
();//暂停oldThread线程,开始litThread,直到litThread
线程结束,oldThread才继续运行,如果不适用Join将小和尚一句,老和尚一句,
随即没有规则的。
for(inti=1;i<=3;i++)
{
ine(i);
}
}
//小和尚念经
staticvoidlitRead()
{
for(inti=4;i<=6;i++)
{
ine(i);
}
}
staticvoidMain(string[]args)
{
oldThread=newThread(newThreadStart(oldRead));
litThread=newThread(newThreadStart(litRead));
();
//();//暂停oldThread线程,开始litThread,直到
litThread线程结束,oldThread才继续运行
();
y();
}
}
多线程互斥锁Mutex
互斥锁是一个同步的互斥对象,适用于,一个共享资源,同时只能有一个线程能够使用。
共享资源加互斥锁,需要两部走:e(),他将处于等待状态知道可以获取资源上的
互斥锁,获取到后,阻塞主线程运行,直到释放互斥锁结束。eMutex(),释放
互斥锁,是其它线程可以获取该互斥锁。
案例:和尚写日记。最近寺庙香火不旺,为啦节约用水,方丈发话两个和尚用一个本子写日
记。
分析:好比多个线程写日志,同时只能有一个线程写入日志文件。
publicclass多线程互斥锁Mutex
{
staticvoidMain(string[]args)
{
IncThreadict=newIncThread("大和尚",3);
DecThreaddct=newDecThread("小和尚",3);
y();
}
}
classSharedRes
{
publicstaticintcount=0;
//初始化互斥锁,没被获取
publicstaticMutexmtx=newMutex();
////初始化互斥锁,被主调线程获取
//publicstaticMutexmtx=newMutex(true);
}
classIncThread
{
intnum;
publicThreadthrd;
publicIncThread(stringname,intn)
{
thrd=newThread(newThreadStart());
=name;
num=n;
();
}
//写日记,过程
voidrun()
{
ine(+",等待互斥锁。");
e();
ine(+",获得互斥锁。");
do
{
(500);
++;
ine("今天我"++"比较强,这样写吧:"+
);
num--;
}while(num>0);
ine(+",释放互斥锁。");
eMutex();
}
}
classDecThread
{
intnum;
publicThreadthrd;
publicDecThread(stringname,intn)
{
thrd=newThread(newThreadStart());
=name;
num=n;
();
}
//写日记,过程
voidrun()
{
ine(+",等待互斥锁。");
e();
ine(+",获得互斥锁。");
do
{
(500);
--;
ine("今天我"++"比较衰,这样写吧:"+
);
num--;
}while(num>0);
ine(+",释放互斥锁。");
eMutex();
}
}
信号量maphore
类似于互斥锁,只不过他可以指定多个线程来访问,共享资源。在初始化信号量的
同时,指定多少个线程可以访问,假如允许2个线程访问,而却有3个线程等待访
问,那么他将只允许2个访问,一旦已访问的2个线程中有一个访问完成释放信号
量,那么没有访问的线程立马可以进入访问。
案例:和尚抓鸡,3个和尚抓鸡,只有两只鸡,那么鸡圈管理员只允许2个和尚先
进,抓到说三句话放下,出来,让第三个和尚进去抓。
分析:三个线程,初始信号量允许2个线程访问。
publicclass信号量maphore
{
staticvoidMain(string[]args)
{
MyThreadtd1=newMyThread("降龙");
MyThreadtd2=newMyThread("伏虎");
MyThreadtd3=newMyThread("如来");
();
();
();
y();
}
}
publicclassMyThread
{
//初始化,新号量,允许2个线程访问,最大2也是2个。
publicstaticSemaphorem=newSemaphore(2,2);
publicThreadtd;
publicMyThread(stringname)
{
td=newThread(newThreadStart());
=name;
}
//过程很美好
publicvoidRun()
{
ine(+",等待一个信号量。");
e();
ine(+",已经获得新号量。");
(500);
//很有深意的三句话
char[]cr={'a','o','e'};
foreach(charvincr)
{
ine(+",输出v:"+v);
(300);
}
ine(+",释放新号量。");
e();
}
}
本文发布于:2022-12-27 04:20:30,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/38066.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |