仓酷云
标题:
JAVA网站制作之Java:多线程守候一切线程停止(CountDownLatch/CyclicBarrier) .仓酷云
[打印本页]
作者:
简单生活
时间:
2015-1-18 11:23
标题:
JAVA网站制作之Java:多线程守候一切线程停止(CountDownLatch/CyclicBarrier) .仓酷云
恰恰证明了java的简单,要不怎么没有通过c/c++来搞个这种框架?本文次要是参考官方文档做一进修用处。
官方链接:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html
复制代码
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CyclicBarrier.html
复制代码
多线程计划过程当中,常常会碰到必要守候别的线程停止今后再做其他事变的情形,好比多线程下载文件,每一个线程城市下载文件的一部分,在一切线程停止今后,必要将各部分再次拼接成一个完全的文件。
有几种计划:
1.在主线程中设置一自界说全局计数标记,在事情线程完成时,计数减一。主线程侦测该标记是不是为0,一旦为0,暗示一切事情线程已完成。
2.利用Java尺度的类CountDownLatch来完成这项事情,道理是一样的,计数。
CountDownLatch
CountDownLatch初始化设置count,即守候(await)count个线程或一个线程count次计数,经由过程事情线程来countDown计数减一,直到计数为0,await堵塞停止。
设置的count不成变动,如必要静态设置计数的线程数,可使用CyclicBarrier.
上面的例子,一切的事情线程中筹办停当今后,并非间接运转,而是守候主线程的旌旗灯号后再实行详细的操纵。
package
com.example.multithread;
import
java.util.concurrent.CountDownLatch;
class
Driver
{
privatestaticfinalint
TOTAL_THREADS=10;
privatefinal
CountDownLatchmStartSignal=
new
CountDownLatch(1);
privatefinal
CountDownLatchmDoneSignal=
new
CountDownLatch(TOTAL_THREADS);
void
main()
{
for
(
int
i=0;i<TOTAL_THREADS;i++)
{
new
Thread(
new
Worker(mStartSignal,mDoneSignal,i)).start();
}
System.out.println("MainThreadNow:"+System.currentTimeMillis());
doPrepareWork();//筹办事情
mStartSignal.countDown();//计数减一为0,事情线程真正启动详细操纵
doSomethingElse();//做点本人的事变
try
{
mDoneSignal.await();//守候一切事情线程停止
}
catch
(InterruptedExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
System.out.println("Allworkershavefinishednow.");
System.out.println("MainThreadNow:"+System.currentTimeMillis());
}
void
doPrepareWork()
{
System.out.println("Ready,GO!");
}
void
doSomethingElse()
{
for
(
int
i=0;i<100000;i++)
{
;//delay
}
System.out.println("MainThreadDosomethingelse.");
}
}
class
Worker
implements
Runnable
{
privatefinal
CountDownLatchmStartSignal;
privatefinal
CountDownLatchmDoneSignal;
privatefinalint
mThreadIndex;
Worker(
final
CountDownLatchstartSignal,
final
CountDownLatchdoneSignal,
finalint
threadIndex)
{
this
.mDoneSignal=doneSignal;
this
.mStartSignal=startSignal;
this
.mThreadIndex=threadIndex;
}
@Override
publicvoid
run()
{
//TODOAuto-generatedmethodstub
try
{
mStartSignal.await();//堵塞,守候mStartSignal计数为0运转前面的代码
//一切的事情线程都在守候统一个启动的命令
doWork();//详细操纵
System.out.println("Thread"+mThreadIndex+"DoneNow:"
+System.currentTimeMillis());
mDoneSignal.countDown();//完成今后计数减一
}
catch
(InterruptedExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
publicvoid
doWork()
{
for
(
int
i=0;i<1000000;i++)
{
;//耗时操纵
}
System.out.println("Thread"+mThreadIndex+":dowork");
}
}
publicclass
CountDownLatchTest
{
publicstaticvoid
main(String[]args)
{
//TODOAuto-generatedmethodstub
new
Driver().main();
}
}
经由过程Executor启动线程:
class
CountDownLatchDriver2
{
privatestaticfinalint
TOTAL_THREADS=10;
privatefinal
CountDownLatchmDoneSignal=
new
CountDownLatch(TOTAL_THREADS);
void
main()
{
System.out.println("MainThreadNow:"+System.currentTimeMillis());
doPrepareWork();//筹办事情
Executorexecutor=Executors.newFixedThreadPool(TOTAL_THREADS);
for
(
int
i=0;i<TOTAL_THREADS;i++)
{
//经由过程内建的线程池保护创立的线程
executor.execute(
new
RunnableWorker(mDoneSignal,i));
}
doSomethingElse();//做点本人的事变
try
{
mDoneSignal.await();//守候一切事情线程停止
}
catch
(InterruptedExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
System.out.println("Allworkershavefinishednow.");
System.out.println("MainThreadNow:"+System.currentTimeMillis());
}
void
doPrepareWork()
{
System.out.println("Ready,GO!");
}
void
doSomethingElse()
{
for
(
int
i=0;i<100000;i++)
{
;//delay
}
System.out.println("MainThreadDosomethingelse.");
}
}
class
RunnableWorker
implements
Runnable
{
privatefinal
CountDownLatchmDoneSignal;
privatefinalint
mThreadIndex;
RunnableWorker(
final
CountDownLatchdoneSignal,
finalint
threadIndex)
{
this
.mDoneSignal=doneSignal;
this
.mThreadIndex=threadIndex;
}
@Override
publicvoid
run()
{
//TODOAuto-generatedmethodstub
doWork();//详细操纵
System.out.println("Thread"+mThreadIndex+"DoneNow:"
+System.currentTimeMillis());
mDoneSignal.countDown();//完成今后计数减一
//计数为0时,主线程打仗堵塞,持续实行其他义务
try
{
//能够持续做点其他的事变,与主线程有关了
Thread.sleep(5000);
System.out.println("Thread"+mThreadIndex
+"Dosomethingelseafternotifingmainthread");
}
catch
(InterruptedExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
publicvoid
doWork()
{
for
(
int
i=0;i<1000000;i++)
{
;//耗时操纵
}
System.out.println("Thread"+mThreadIndex+":dowork");
}
}
输入:
MainThreadNow:1359959480786Ready,GO!Thread0:doworkThread0DoneNow:1359959480808Thread1:doworkThread1DoneNow:1359959480811Thread2:doworkThread2DoneNow:1359959480813MainThreadDosomethingelse.Thread3:doworkThread3DoneNow:1359959480825Thread5:doworkThread5DoneNow:1359959480827Thread7:doworkThread7DoneNow:1359959480829Thread9:doworkThread9DoneNow:1359959480831Thread4:doworkThread4DoneNow:1359959480833Thread6:doworkThread6DoneNow:1359959480835Thread8:doworkThread8DoneNow:1359959480837Allworkershavefinishednow.MainThreadNow:1359959480838Thread0DosomethingelseafternotifingmainthreadThread1DosomethingelseafternotifingmainthreadThread2DosomethingelseafternotifingmainthreadThread3DosomethingelseafternotifingmainthreadThread9DosomethingelseafternotifingmainthreadThread7DosomethingelseafternotifingmainthreadThread5DosomethingelseafternotifingmainthreadThread4DosomethingelseafternotifingmainthreadThread6DosomethingelseafternotifingmainthreadThread8Dosomethingelseafternotifingmainthread
复制代码
CyclicBarrier
复制代码
利用CyclickBarrier的例子:
复制代码
class
WalkTarget
{
privatefinalint
mCount=5;
privatefinal
CyclicBarriermBarrier;
ExecutorServicemExecutor;
class
BarrierAction
implements
Runnable
{
@Override
publicvoid
run()
{
//TODOAuto-generatedmethodstub
System.out.println("一切线程都已完成义务,计数到达预设值");
//mBarrier.reset();//恢复到初始化形态
}
}
WalkTarget()
{
//初始化CyclicBarrier
mBarrier=
new
CyclicBarrier(mCount,
new
BarrierAction());
mExecutor=Executors.newFixedThreadPool(mCount);
for
(
int
i=0;i<mCount;i++)
{
//启开工作线程
mExecutor.execute(
new
Walker(mBarrier,i));
}
}
}
//事情线程
class
Walker
implements
Runnable
{
privatefinal
CyclicBarriermBarrier;
privatefinalint
mThreadIndex;
Walker(
final
CyclicBarrierbarrier,
finalint
threadIndex)
{
mBarrier=barrier;
mThreadIndex=threadIndex;
}
@Override
publicvoid
run()
{
//TODOAuto-generatedmethodstub
System.out.println("Thread"+mThreadIndex+"isrunning...");
//实行义务
try
{
TimeUnit.MILLISECONDS.sleep(5000);
//dotask
}
catch
(InterruptedExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
//完成义务今后,守候其他线程完成义务
try
{
mBarrier.await();
}
catch
(InterruptedExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
catch
(BrokenBarrierExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
//其他线程义务都完成今后,堵塞排除,能够持续接上去的义务
System.out.println("Thread"+mThreadIndex+"dosomethingelse");
}
}
publicclass
CountDownLatchTest
{
publicstaticvoid
main(String[]args)
{
//TODOAuto-generatedmethodstub
//newCountDownLatchDriver2().main();
new
WalkTarget();
}
}
输入(注重,只要一切的线程barrier.await以后才干持续实行其他的操纵):
Thread0isrunning...Thread2isrunning...Thread3isrunning...Thread1isrunning...Thread4isrunning...一切线程都已完成义务,计数到达预设值Thread4dosomethingelseThread0dosomethingelseThread2dosomethingelseThread3dosomethingelseThread1dosomethingelse
复制代码
CountDownLatch和CyclicBarrier复杂对照:
<p>CountDownLatch
CyclicBarrier
软件包
java.util.concurrent
java.util.concurrent
合用情形
主线程守候多个事情线程停止
多个线程之间相互守候,直到一切线程到达一个停滞点(Barrierpoint)
次要办法
CountDownLatch(intcount)(主线程挪用)
初始化计数
CountDownLatch.await(主线程挪用)
堵塞,直到守候计数为0排除堵塞
CountDownLatch.countDown
Java的B/s开发是通常是javaweb开发,又叫J2EE开发,J2SE是手机开发。C#的C/s和B/s开发是说.net网页编程和Asp开发。。u在这里说明一点;资深一点的Java和C#程序员都明白一点
作者:
若天明
时间:
2015-1-19 20:41
其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。
作者:
冷月葬花魂
时间:
2015-1-24 16:19
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
作者:
飘飘悠悠
时间:
2015-1-25 22:41
是一种语言,用以产生「小应用程序(Applet(s))
作者:
第二个灵魂
时间:
2015-1-27 20:07
是一种语言,用以产生「小应用程序(Applet(s))
作者:
柔情似水
时间:
2015-2-5 09:14
你现在最缺的是实际的工作经验,而不是书本上那些凭空想出来的程序。
作者:
兰色精灵
时间:
2015-2-11 08:21
象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。
作者:
愤怒的大鸟
时间:
2015-3-1 09:03
至于JDBC,就不用我多说了,你如果用java编过存取数据库的程序,就应该很熟悉。还有,如果你要用Java编发送电子邮件的程序,你就得看看Javamail 了。
作者:
飘灵儿
时间:
2015-3-2 08:46
还好,SUN提供了Javabean可以把你的JSP中的 Java代码封装起来,便于调用也便于重用。
作者:
若相依
时间:
2015-3-11 02:39
象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。
作者:
海妖
时间:
2015-3-17 19:09
是一种语言,用以产生「小应用程序(Applet(s))
作者:
因胸联盟
时间:
2015-3-24 20:36
学Java必读的两个开源程序就是Jive和Pet Store.。 Jive是国外一个非常著名的BBS程序,完全开放源码。论坛的设计采用了很多先进的技术,如Cache、用户认证、Filter、XML等,而且论坛完全屏蔽了对数据库的访问,可以很轻易的在不同数据库中移植。论坛还有方便的安装和管理程序,这是我们平时编程时容易忽略的一部份(中国程序员一般只注重编程的技术含量,却完全不考虑用户的感受,这就是我们与国外软件的差距所在)。
欢迎光临 仓酷云 (http://ckuyun.com/)
Powered by Discuz! X3.2