`
brzone
  • 浏览: 2685 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

java同步器

    博客分类:
  • java
阅读更多

    在jdk1.5的concurrent包下提供了一些有意思的同步器,以前做线程间的通信用的就是wait,notify,现在在concurrent包下一句封装了细节,让我们在更高的层次上进行线程间的同步、通信。
   
  
  一:CyclicBarrier
        循环屏障点,它允许一组线程相互等待,知道到达某个屏障点Brrrier.套用《java并发编程实践》书籍中的例子就是,当几个旅行团要途径A、B、C,其中这几个旅行团做的坐的交通工具不相同,有1绿色1路车,有自驾游,有坐大巴,但是有一条,在到达某一个点,比方这里是A,先到的必须要等待后到的,直到全部到达,然后,才出发第二点个点。
     模拟的程序如下(例子出处《java并发编程实践》,因为我想不到其他更好一点的例子)

/**
 *
 * @author li jian
 * @mail brzone@126.com
 * @date 2012-9-10 下午05:12:18
 */
public class RunTask implements Runnable {

	private CyclicBarrier barrier;

	private int[] SencondTimeForWait;

	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	public RunTask(CyclicBarrier barrier, int[] sencondTimeForWait) {
		super();
		this.barrier = barrier;
		SencondTimeForWait = sencondTimeForWait;
	}

	@Override
	public void run() {

		for(int stepTime: SencondTimeForWait) {

			try {
				TimeUnit.SECONDS.sleep(stepTime);
				System.out.println(getCurrentTime() 
                                +  "\t" + Thread.currentThread().getName() 
                                +  " has reached.");



				/**
				 * 当到达某一个屏障点,就等待。
				 *
				 * 可以利用类似信号量来做比方:
				 *              刚刚开始的信号量,是new出来CyclicBarrier传进去的值,
				 *              这里是3,可以理解是:await()一次,其信号量减1,然后
				 *              进入堵塞,直到信号量为0,此时,唤醒全部堵塞的线程,使
				 *              其线程全部继续执行,并把信号量恢复到原来创建时的值,
				 *              这样便可以循环的执行下去。
				 *
				 *
				 */

				barrier.await();

			} catch (InterruptedException e) {

				e.printStackTrace();
				throw new RuntimeException(e);
			} catch (BrokenBarrierException e) {

				e.printStackTrace();
				throw new RuntimeException(e);
			}


		}

	}


	private String getCurrentTime() {

		return sdf.format(new java.util.Date());
	}


	/**
	 * just for test Date format is ok
	 * @param args
	 */
	public static void main(String[] args) {

		System.out.println(sdf.format(new java.util.Date()));

	}

}

 

/**
 *
 * @author li jian
 * @mail brzone@126.com
 * @date 2012-9-10 下午05:03:22
 */
public class CyclicBarrierDemo {

	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


	public static void main(String[] args) {

		int[] walkTime = {5,8,10};

		int[] driverCarBySelf = {1,2,3};

		int[] driverbus = {2,4,6};

		//当到达某一屏障点的时候,由最后一个到达屏障点的线程执行该任务。
		CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {

			@Override
			public void run() {
				System.out.println(sdf.format(new java.util.Date()) 
						+ "\t" + Thread.currentThread().getName()
						+ "\twe all reached.");

			}
		});

		//起三个线程执行器
		ExecutorService exec = Executors.newFixedThreadPool(3);
		//执行任务
		exec.submit(new RunTask(barrier, walkTime));
		exec.submit(new RunTask(barrier, driverCarBySelf));
		exec.submit(new RunTask(barrier, driverbus));

		exec.shutdown();

	}

}



打出日志:
2012-09-10 17:17:22 pool-1-thread-2 has reached.
2012-09-10 17:17:23 pool-1-thread-3 has reached.
2012-09-10 17:17:26 pool-1-thread-1 has reached.
2012-09-10 17:17:26 pool-1-thread-1 we all reached.
2012-09-10 17:17:28 pool-1-thread-2 has reached.
2012-09-10 17:17:30 pool-1-thread-3 has reached.
2012-09-10 17:17:34 pool-1-thread-1 has reached.
2012-09-10 17:17:34 pool-1-thread-1 we all reached.
2012-09-10 17:17:37 pool-1-thread-2 has reached.
2012-09-10 17:17:40 pool-1-thread-3 has reached.
2012-09-10 17:17:44 pool-1-thread-1 has reached.
2012-09-10 17:17:44 pool-1-thread-1 we all reached.


很明显是最晚到达一个thread打出到达屏障点的Runnable,且在都到达屏障点后才继续执行。


二:CountDownLatch
    可以利用CountDownLatch,在多个线程完成任务之前一直等待,例如多线程下载,合并的线程是在下载线程都执行完才工作的,下面举个老师和同学的例子,如下:

/**
 * 学生
 * @author li jian
 * @mail brzone@126.com
 * @date 2012-9-11 下午05:27:06
 */
public class StudentTask implements Runnable{

	private CountDownLatch latch;

	private String name;

	private static final Random random  = new Random(37);

	public StudentTask(String name,CountDownLatch latch) {
		super();
		this.latch = latch;
		this.name = name;
	}

	@Override
	public void run() {

		doWork();

		try {

			//为了效果,随机休眠秒数
			TimeUnit.SECONDS.sleep(random.nextInt(4));

		} catch (InterruptedException e) {

			e.printStackTrace();
			throw new RuntimeException(e);
		}

		//做完自己的事情后,便要使计数器减一
		latch.countDown();

	}

	private void doWork() {

		System.out.println(Thread.currentThread().getName()
				+ "\t" + name + " has here.");
	}

}

 

/**
 * 老师
 * @author li jian
 * @mail brzone@126.com
 * @date 2012-9-11 下午05:14:44
 */
public class TeacherTask implements Runnable {

	private CountDownLatch latch;

	public TeacherTask(CountDownLatch latch) {
		super();
		this.latch = latch;
	}

	@Override
	public void run() {

		try {

		   //在计数器不能0的时候,该方法会一直堵塞,直至计数器为0
			latch.await();
            doWork();
		} catch (InterruptedException e) {

			e.printStackTrace();
			throw new RuntimeException(e);
		}


	}

	private void doWork() {

		System.out.println("we can attend class.");

	}

}

 

/**
 * 测试类
 * @author li jian
 * @mail brzone@126.com
 * @date 2012-9-11 下午05:20:26
 */
public class Client {

	public static void main(String[] args) {

		/**
		 *我们在这里约定,有10个学生,2个老师,
		 *老师,必须要等待10个学生全部到课堂
		 * 才可以进行教学。
		 *
		 */

		/*既然是要等待10个学生,当然计数器为10*/
		CountDownLatch latch = new CountDownLatch(10);

		ExecutorService exec = Executors.newFixedThreadPool(5);

		/**
		 *
		 * 在这里,就算是老师先执行,但是,在老师的run
		 * 方法中latch.await(),老师们要等待CountDownLatch
		 * 的计数器为0,就是要10个学生都执行latch.countDown(),
		 * 然后老师们才可以做自己的事情,在计数器不为0的
		 * 情况下是一直堵塞的。
		 *
		 *
		 * tip:
		 *     细心的你,是否有没有发现一个小bug,就是只要一个
		 *     老师来了,也就可以上课了,在这里,我们暂且约定
		 *     老师们是一起来的。
		 *
		 */

		for(int i = 0;i<2;i++) {

			exec.execute(new TeacherTask(latch));

		}

		for(int i=0;i<10;i++) {

			exec.execute(new StudentTask("s" + i, latch));

		}


		exec.shutdown();

	}

}



打印日志:
pool-1-thread-4 s1 has here.
pool-1-thread-3 s0 has here.
pool-1-thread-5 s2 has here.
pool-1-thread-3 s3 has here.
pool-1-thread-3 s4 has here.
pool-1-thread-4 s5 has here.
pool-1-thread-4 s6 has here.
pool-1-thread-5 s7 has here.
pool-1-thread-5 s8 has here.
pool-1-thread-4 s9 has here.
we can attend class.
we can attend class.


日志中,显而易见。

当然还有其他的同步器,如Semaphore,Exchanger
,可以用到时在做学习啦

 

0
0
分享到:
评论
4 楼 brzone 2012-09-11  
freezingsky 写道
实现的方式有好几个,特别是在JAVA的并发包,提供一种便利的方式。但深入来讲,原理还是那些:互斥、信号量。

你说的对。 
3 楼 brzone 2012-09-11  
leonayx123 写道
我现在一直用的 CountDownLatch latch = new CountDownLatch(size);
初始一个计数锁
调用latch.await(); 让线程等待
直到
latch.countDown();所有的计数后,再执行

CountDownLatch,嗯嗯,最近又在温习《java并发编程实践》一遍,总觉得要写些什么,下面还要说像你的CountDownLatch。你说的很对,总体来说,CyclicBarrier就是相当于多个CountDownLatch,呵呵。
2 楼 freezingsky 2012-09-11  
实现的方式有好几个,特别是在JAVA的并发包,提供一种便利的方式。但深入来讲,原理还是那些:互斥、信号量。
1 楼 leonayx123 2012-09-11  
我现在一直用的 CountDownLatch latch = new CountDownLatch(size);
初始一个计数锁
调用latch.await(); 让线程等待
直到
latch.countDown();所有的计数后,再执行

相关推荐

    java 同步器SynchronousQueue详解及实例

    Java 同步器 SynchronousQueue 详解及实例 Java 中的同步器 SynchronousQueue 是一种特殊的阻塞队列,它最多只能放一个元素,这个元素如果不在特定的时间消费掉就会被删除,队列的长度始终为 0。SynchronousQueue ...

    java同步大杀器concurrent 包

    java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大...

    java并发编程之同步器代码示例

    Java并发编程之同步器代码示例 Java并发编程中,同步器是一种使线程能够等待另一个线程的对象,允许它们协调动作。常用的同步器有CountDownLatch、Semaphore、Barrier和Exchanger队列同步器等。...

    The java.util.concurrent Synchronizer Framework

    Java同步器框架的核心目标是在多线程设计中提供高效、灵活的同步工具,其设计和实现考虑到了在多核处理器上运行的环境,尤其是面对线程竞争时的性能问题。为了达到这一目标,该框架设计了一系列接口和类,包括互斥锁...

    Java多线程同步器代码详解

    Java多线程同步器在并发编程中扮演着至关重要的角色,它们帮助开发者管理线程间的协作,确保资源的正确访问和程序的顺序执行。本文将深入解析四种主要的同步器:CountDownLatch、Semaphore、Barrier和Exchanger,并...

    Java分布式应用学习笔记05多线程下的并发同步器

    ### Java分布式应用学习笔记05多线程下的并发同步器 #### 1. 前言 在现代软件开发中,特别是在分布式系统和高性能计算领域,有效地管理多线程之间的协同工作至关重要。Java语言提供了丰富的工具和API来帮助开发者...

    java同步synchronized关键字用法示例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源时的同步机制。在Java中,当多个线程试图同时访问和修改同一块代码或数据时,可能会导致数据不一致的问题。为了解决这个问题,...

    深入学习Java同步机制中的底层实现

    Java同步机制是多线程编程中确保数据一致性与正确性的关键。在Java中,主要有两种同步机制:内置的`synchronized`关键字以及基于`java.util.concurrent`包中的高级同步工具类。本文将深入探讨这些机制的底层实现,...

    java同步歌词功能

    Java同步歌词功能是一种在音乐播放器中常见的特性,它允许用户在欣赏音乐的同时,看到与当前播放时间对应的歌词。这项功能的实现主要依赖于Java编程语言以及对LRC(Lyric Repeat Character)格式的文本文件处理。LRC...

    java同步异步知识

    ### Java中的同步与异步详解 #### 一、同步与异步的概念理解 在软件开发领域,特别是针对并发处理和网络编程时,我们经常会遇到“同步”与“异步”这两个概念。简单来说: - **同步(Synchronous)**:指的是程序...

    时间同步器(附源码).zip

    时间同步器是一款重要的软件工具,尤其在分布式系统和网络环境中,确保系统时钟的一致性至关重要。本资源提供了一个时间同步器的源码,可以帮助开发者深入理解时间同步的原理,并可作为开发相关应用的基础。 时间...

    Java实现进程同步

    Java作为一种强大的多线程编程语言,提供了丰富的API来支持进程同步。本篇文章将深入探讨如何使用Java实现“生产者-消费者”问题的进程同步。 生产者-消费者问题是多线程设计模式中的一个经典案例,它模拟了两个...

    Java并发编程解析 | 解析AQS基础同步器的设计与实现

    "Java并发编程解析 | 解析AQS基础同步器的设计与实现" 在Java领域中,解决并发编程问题的关键是解决同步和互斥的问题。同步是指线程之间的通信和协作,互斥是指同一时刻只能允许一个线程访问共享资源。Java领域中有...

    java同步(一个网页)

    Java同步是Java编程中一个非常重要的概念,主要涉及到多线程环境下的程序控制。在Java中,当多个线程同时访问共享资源时,如果没有适当的同步机制,可能会导致数据不一致、竞态条件等问题。同步机制确保了在特定时间...

    Java画图板,支持网络同步

    在Java中,事件监听器可以捕获用户的绘图动作,如鼠标点击和拖动,而多线程则保证了在网络通信的同时不影响用户界面的响应速度。为了保证数据的一致性,可能还用到了版本控制或并发控制机制,如乐观锁或悲观锁。 在...

    Java文件同步程序

    这可以通过文件系统的监听器(如Java的WatchService API)来实现。 2. **文件传输**:文件的传输通常采用TCP/IP协议,通过Socket建立连接,然后利用输入输出流读取和写入文件内容。为了提高效率,可以使用断点续传...

    Java同步框架AbstractQueuedSynchronizer详解

    Java同步框架AbstractQueuedSynchronizer详解 AbstractQueuedSynchronizer(AQS)是Java中的一个同步框架类,它实现了最核心的多线程同步的语义。AQS提供了一个基础的同步器实现,开发者可以通过继承AQS来实现自己...

    java线程同步实例

    根据提供的信息,我们可以深入探讨Java线程同步以及代码示例中的关键知识点。 ### Java线程同步实例:哲学家就餐问题 #### 1. 哲学家就餐问题简介 哲学家就餐问题是多线程编程中一个经典的同步问题。该问题描述为...

    Java并发编程:深入解析抽象队列同步器(AQS)及其在Lock中的应用

    本文深入探讨了Java并发编程的关键组件——抽象队列同步器(AQS)及其在ReentrantLock的应用。AQS是处理线程同步问题的高效工具,是Java并发编程中的核心。文章首先简要介绍了并发编程领域的先驱Doug Lea。重点在于...

    java计时器经典例子

    在实际应用中,Java计时器常用于更新UI、执行定期任务,如数据同步、检查更新等。计时器还提供了暂停、恢复和停止功能,这可以通过调用`timer.stop()`、`timer.setRepeats(false)`和`timer.restart()`方法实现。 ...

Global site tag (gtag.js) - Google Analytics