Java线程类一

一、java.util.concurrent.CountDownLatch

通常线程是并发运行,并且不容易预测到哪个线程先执行,哪些后执行,所以通常在执行顺序上是相当公平的。但是,因为创建对象或者执行某些操作总是需要一定的时间,所以还是很难保证真正的公平。这时就需要某种机制来控制线程的运行时机。就比如说赛跑,必须等待所有的选手都已经站在起跑线上才能开始,而java.util.concurrent.CountDownLatch就是这样一个控制器,用于保证所有选手都在起跑线上。

 

例如以下程序: 

		for(int i = 0;i< 10;i++){
			new Thread("Thread "+i){
				public void run() {
					System.out.println(getName()+" started");
				}
			}.start();
			Thread.sleep(50);
		}

如果没有某种保证机制,那基本上可以预测结果如下:

Thread 0 started
Thread 1 started
Thread 2 started
Thread 3 started
Thread 4 started
Thread 5 started
Thread 6 started
Thread 7 started
Thread 8 started
Thread 9 started

因为后面的线程还没开始创建,前面的线程已经启跑了。

 

为了让他们在同一时间开跑,而不管创建的时机,可以如下:

//创建CountDownLatch,并指定countDown必须被调用10次
final CountDownLatch countDownLatch = new CountDownLatch(10);

for(int i = 0;i< 10;i++){
	new Thread("Thread "+i){
		public void run() {
			try {
				//在继续运行之前等待条件满足,也即所有的线程都准备好
				countDownLatch.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(getName()+" started");
		}
	}.start();
	Thread.sleep(50);
	//每创建完一个线程,调用一次countDown()方法,当高用到10次时,即条件满足
	countDownLatch.countDown();
}

下面是某次运行的结果:

Thread 0 started
Thread 8 started
Thread 7 started
Thread 6 started
Thread 5 started
Thread 1 started
Thread 3 started
Thread 2 started
Thread 4 started
Thread 9 started

同上面的结果比较,可以看出,结果基本已经是不可测的了。并且,所以的线程会在等待了差不多半秒之后同步运行。

 

简单的说 java.util.concurrent.CountDownLatch 就是一个倒数器,倒数到 0 后就开始执行所有等待的操作。

 

二、java.util.concurrent.CyclicBarrier

上面的 java.util.concurrent.CountDownLatch 可以用于控制线程同时执行,而 java.util.concurrent.CyclicBarrier 则可以用来控制线程收尾工作。例如,还是上面那个线程,如果我们想在所有的线程执行完后,再打印一下 Done ,则可以如下实现:

final CyclicBarrier cyclicBarrier = new CyclicBarrier(10, new Runnable() {
	
	@Override
	public void run() {
		System.out.println("Done");
	}
});

for(int i = 0; i<10;i++){
	new Thread("Thread "+i){
		public void run() {
			System.out.println(getName());
			try {
				cyclicBarrier.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
			}
		}
	}.start();
}

运行结果如下:

Thread 0
Thread 1
Thread 5
Thread 3
Thread 6
Thread 4
Thread 7
Thread 8
Thread 2
Thread 9
Done

根据提示可以看到,它可以用于做收尾工作,比如说我们有一个查找程序,其中使用了多线程去分别查找,然后可以最后使用 CyclicBarrier 来将结果合并(当然也有其他的方法,这里只是说它可以做这件事)。

三、java.util.concurrent.Semaphore

信号量用于控制同时访问某一资源的线程数,例如系统上的某个文件,只想被最多5个线程同时使用,就可以用信号量在控制了。每次同过 acquire() 方法,获取访问权限,同时信号量减1,当信号量减为0时则不能有新的线程再获得权限;用release()方法释放权限,信号量加1,则可以有新的线程获得权限,例如:

		final Semaphore semaphore = new Semaphore(2, true);
		
		for(int i = 0;i<5;i++){
			new Thread("Thread "+i){
				public void run() {
					try {
						String threadName = getName();
						System.out.println(threadName+"\t is waiting");
						semaphore.acquire();
						System.out.println(threadName+"\t is running");
						sleep(30000);
						System.out.println(threadName+"\t is finished");
					} catch (InterruptedException e) {
						e.printStackTrace();
					}finally{
						semaphore.release();
					}
				}
				
			}.start();
		}

某次运行的结果:

Thread 0	 is waiting
Thread 1	 is waiting
Thread 1	 is running
Thread 3	 is waiting
Thread 4	 is waiting
Thread 0	 is running
Thread 2	 is waiting

可以看到,5个线程都启动了,但是只有2个线程进入了running状态,其他3个处于waiting状态,30秒之后,先前2个running状态的线程finish了之后,剩下其中2个等待的线程才有机会开始进入运行状态:

Thread 1	 is finished
Thread 0	 is finished
Thread 3	 is running
Thread 4	 is running

 

四、java.util.concurrent.Phaser

Java 7中新增了Phaser类,它有点类似于上面介绍的CyclicBarrier和CountDownLatch,但是它支持多阶段的运行/等待,并且支持增加移除观察者。比如说某个操作需要3步完成,其中每一步都需要多个线程配合:

		final Phaser phaser = new Phaser(5);
		for(int i = 0;i<5;i++){
			new Thread("Thread "+i){
				public void run() {
					System.out.println(getName()+" are ready");
					phaser.arriveAndAwaitAdvance();
					System.out.println(getName()+" finished phase1");
					
					phaser.arriveAndAwaitAdvance();
					System.out.println(getName()+" finished phase2");
				}
			}.start();
		}

 某次运行的结果可能如下:

Thread 0 are ready
Thread 2 are ready
Thread 1 are ready
Thread 3 are ready
Thread 4 are ready
Thread 4 finished phase1
Thread 1 finished phase1
Thread 3 finished phase1
Thread 0 finished phase1
Thread 2 finished phase1
Thread 2 finished phase2
Thread 1 finished phase2
Thread 3 finished phase2
Thread 0 finished phase2
Thread 4 finished phase2

 也可以像CyclicBarrier一样,当满足某个条件时才开始工作,例如:

		final Phaser phaser = new Phaser(5);
		phaser.register();
		for(int i = 0;i<5;i++){
			new Thread("Thread "+i){
				public void run() {
					System.out.println(getName()+" are ready");
					phaser.arriveAndAwaitAdvance();
					System.out.println(getName()+" finished phase1");
					
					phaser.arriveAndAwaitAdvance();
					System.out.println(getName()+" finished phase2");
				}
			}.start();
		}
		System.out.println("Wait for a moment before start");
		Thread.sleep(2000);
		phaser.arriveAndDeregister();

一开始可能输出:

Thread 0 are ready
Thread 2 are ready
Thread 1 are ready
Wait for a moment before start
Thread 3 are ready
Thread 4 are ready

2秒后接着输出:

Thread 3 finished phase1
Thread 0 finished phase1
Thread 2 finished phase1
Thread 4 finished phase1
Thread 1 finished phase1
Thread 1 finished phase2
Thread 3 finished phase2
Thread 4 finished phase2
Thread 2 finished phase2
Thread 0 finished phase2

 可以通过重写它的onAdvance()方法来实现在每个阶段结束后执行某个自定义的操作:

		final Phaser phaser = new Phaser(5){
			@Override
			protected boolean onAdvance(int phase, int registeredParties) {
				System.out.println("============="+phase+"=============");
				return super.onAdvance(phase, registeredParties);
			}
		};
		phaser.register();
		for(int i = 0;i<5;i++){
			new Thread("Thread "+i){
				public void run() {
					System.out.println(getName()+" are ready");
					phaser.arriveAndAwaitAdvance();
					System.out.println(getName()+" finished phase1");
					
					phaser.arriveAndAwaitAdvance();
					System.out.println(getName()+" finished phase2");
				}
			}.start();
		}
		System.out.println("Wait for a moment before start");
		Thread.sleep(2000);
		phaser.arriveAndDeregister();

这里在每个阶段的条件满足后插入一段分隔符,输出结果可能为:

Thread 0 are ready
Thread 2 are ready
Thread 1 are ready
Wait for a moment before start
Thread 4 are ready
Thread 3 are ready
=============0=============
Thread 3 finished phase1
Thread 1 finished phase1
Thread 2 finished phase1
Thread 0 finished phase1
Thread 4 finished phase1
=============1=============
Thread 4 finished phase2
Thread 3 finished phase2
Thread 2 finished phase2
Thread 0 finished phase2
Thread 1 finished phase2

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值