`

Synchronizer 类

 
阅读更多

 

Synchronizer 类

Synchronizer

java.util.concurrent 中其他类别的有用的类也是同步工具。这组类相互协作,控制一个或多个线程的执行流。

SemaphoreCyclicBarrierCountdownLatch 和 Exchanger 类都是同步工具的例子。每个类都有线程可以调用的方法,方法是否被阻塞取决于正在使用的特定同步工具的状态和规则。

Semaphore

Semaphore 类实现标准 Dijkstra 计数信号。计数信号可以认为具有一定数量的许可权,该许可权可以获得或释放。如果有剩余的许可权,acquire() 方法将成功,否则该方法将被阻塞,直到有可用的许可权(通过其他线程释放许可权)。线程一次可以获得多个许可权。

计数信号可以用于限制有权对资源进行并发访问的线程数。该方法对于实现资源池或限制 Web 爬虫(Web crawler)中的输出 socket 连接非常有用。

注意信号不跟踪哪个线程拥有多少许可权;这由应用程序来决定,以确保何时线程释放许可权,该信号表示其他线程拥有许可权或者正在释放许可权,以及其他线程知道它的许可权已释放。

互斥

计数信号的一种特殊情况是互斥,或者互斥信号。互斥就是具有单一许可权的计数信号,意味着在给定时间仅一个线程可以具有许可权(也称为二进制信号)。互斥可以用于管理对共享资源的独占访问。

虽然互斥许多地方与锁定一样,但互斥还有一个锁定通常没有的其他功能,就是互斥可以由具有许可权的线程之外的其他线程来释放。这在死锁恢复时会非常有用。

CyclicBarrier

CyclicBarrier 类可以帮助同步,它允许一组线程等待整个线程组到达公共屏障点。CyclicBarrier 是使用整型变量构造的,其确定组中的线程数。当一个线程到达屏障时(通过调用 CyclicBarrier.await()),它会被阻塞,直到所有线程都到达屏障,然后在该点允许所有线程继续执行。该操作与许多家庭逛商业街相似 —— 每个家庭成员都自己走,并商定 1:00 在电影院集合。当您到电影院但不是所有人都到了时,您会坐下来等其他人到达。然后所有人一起离开。

认为屏障是循环的是因为它可以重新使用;一旦所有线程都已经在屏障处集合并释放,则可以将该屏障重新初始化到它的初始状态。

还可以指定在屏障处等待时的超时;如果在该时间内其余线程还没有到达屏障,则认为屏障被打破,所有正在等待的线程会收到BrokenBarrierException

下列代码将创建 CyclicBarrier 并启动一组线程,每个线程将计算问题的一部分,等待所有其他线程结束之后,再检查解决方案是否达成一致。如果不一致,那么每个工作线程将开始另一个迭代。该例将使用 CyclicBarrier 变量,它允许注册 Runnable,在所有线程到达屏障但还没有释放任何线程时执行 Runnable

class Solver { // Code sketch

  void solve(final Problem p, int nThreads) {
  final CyclicBarrier barrier = 
    new CyclicBarrier(nThreads,
      new Runnable() {
        public void run() { p.checkConvergence(); }}
    );
    for (int i = 0; i < nThreads; ++i) {
      final int id = i;
      Runnable worker = new Runnable() {
        final Segment segment = p.createSegment(id);
        public void run() {
          try {
            while (!p.converged()) {
              segment.update();
              barrier.await();
            }
          }
          catch(Exception e) { return; }
        }
      };
      new Thread(worker).start();
   }
}
 

CountdownLatch

CountdownLatch 类与 CyclicBarrier 相似,因为它的角色是对已经在它们中间分摊了问题的一组线程进行协调。它也是使用整型变量构造的,指明计数的初始值,但是与 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。

其中,CyclicBarrier 是到达屏障的所有线程的大门,只有当所有线程都已经到达屏障或屏障被打破时,才允许这些线程通过,CountdownLatch 将到达和等待功能分离。任何线程都可以通过调用 countDown() 减少当前计数,这种不会阻塞线程,而只是减少计数。await() 方法的行为与 CyclicBarrier.await() 稍微有所不同,调用 await() 任何线程都会被阻塞,直到闩锁计数减少为零,在该点等待的所有线程才被释放,对 await() 的后续调用将立即返回。

当问题已经分解为许多部分,每个线程都被分配一部分计算时,CountdownLatch 非常有用。在工作线程结束时,它们将减少计数,协调线程可以在闩锁处等待当前这一批计算结束,然后继续移至下一批计算。

相反地,具有计数 1 的 CountdownLatch 类可以用作“启动大门”,来立即启动一组线程;工作线程可以在闩锁处等待,协调线程减少计数,从而立即释放所有工作线程。下例使用两个 CountdownLatche。一个作为启动大门,一个在所有工作线程结束时释放线程:

 

class Driver { 
   void main() throws InterruptedException {
     CountDownLatch startSignal = new CountDownLatch(1);
     CountDownLatch doneSignal = new CountDownLatch(N);

     for (int i = 0; i < N; ++i) // create and start threads
       new Thread(new Worker(startSignal, doneSignal)).start();

     doSomethingElse();            // don't let them run yet
     startSignal.countDown();      // let all threads proceed
     doSomethingElse();
     doneSignal.await();           // wait for all to finish
   }
 }

 class Worker implements Runnable {
   private final CountDownLatch startSignal;
   private final CountDownLatch doneSignal;
   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
      this.startSignal = startSignal;
      this.doneSignal = doneSignal;
   }
   public void run() {
      try {
        startSignal.await();
        doWork();
        doneSignal.countDown();
      } catch (InterruptedException ex) {} // return;
   }
 }
 

Exchanger

Exchanger 类方便了两个共同操作线程之间的双向交换;这样,就像具有计数为 2 的 CyclicBarrier,并且两个线程在都到达屏障时可以“交换”一些状态。(Exchanger 模式有时也称为聚集。)

Exchanger 通常用于一个线程填充缓冲(通过读取 socket),而另一个线程清空缓冲(通过处理从 socket 收到的命令)的情况。当两个线程在屏障处集合时,它们交换缓冲。下列代码说明了这项技术:

 

class FillAndEmpty {
   Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
   DataBuffer initialEmptyBuffer = new DataBuffer();
   DataBuffer initialFullBuffer = new DataBuffer();

   class FillingLoop implements Runnable {
     public void run() {
       DataBuffer currentBuffer = initialEmptyBuffer;
       try {
         while (currentBuffer != null) {
           addToBuffer(currentBuffer);
           if (currentBuffer.full())
             currentBuffer = exchanger.exchange(currentBuffer);
         }
       } catch (InterruptedException ex) { ... handle ... }
     }
   }

   class EmptyingLoop implements Runnable {
     public void run() {
       DataBuffer currentBuffer = initialFullBuffer;
       try {
         while (currentBuffer != null) {
           takeFromBuffer(currentBuffer);
           if (currentBuffer.empty())
             currentBuffer = exchanger.exchange(currentBuffer);
         }
       } catch (InterruptedException ex) { ... handle ...}
     }
   }

   void start() {
     new Thread(new FillingLoop()).start();
     new Thread(new EmptyingLoop()).start();
   }
 }
 

 

分享到:
评论

相关推荐

    hibernatesynchronizer_3.1.9

    Hibernate Synchronizer是基于Eclipse的一款插件,其核心功能在于实现Java实体类与数据库表结构之间的双向同步。它能够自动检测数据库更改,并相应地更新实体类;反之,当修改了实体类后,也能同步更新数据库表结构...

    Hibernate Synchronizer2.3.1.rar

    在Hibernate Synchronizer 2.3.1版本中,开发者可以享受到更为高效、便捷的数据库模型与Java类之间的同步体验。 首先,我们来深入理解Hibernate Synchronizer的核心功能。这款工具主要解决了开发过程中的一大痛点:...

    HibernateSynchronizer-3.1.9

    《HibernateSynchronizer 3.1.9:数据库与对象模型同步的利器》 HibernateSynchronizer是一款基于Java的开源工具,专为开发者设计,用于实现数据库与对象模型的自动同步。这个工具的核心功能在于帮助开发者高效地...

    HibernateSynchronizer3扩展JPA

    《HibernateSynchronizer3:扩展JPA的利器》 在当今的软件开发中,Java持久化API(JPA)和Hibernate框架是企业级应用的重要组成部分,它们为开发者提供了方便的数据访问和对象关系映射(ORM)功能。然而,随着项目...

    Hibernate Synchronizer

    - **自动映射**: Hibernate Synchronizer可以根据现有的数据库模式自动生成对应的Java实体类,这样开发者无需手动编写这些类。只需指定数据库连接信息,插件会自动识别表结构并创建相应的Entity类。 - **逆向工程**...

    安装Hibernate Synchronizer

    尤其对于那些需要频繁地将数据库模型与Java实体类进行同步的项目而言,Hibernate Synchronizer具有非常重要的作用。 #### Eclipse IDE与插件管理 Eclipse是一款广泛使用的开源集成开发环境,支持多种编程语言。...

    HibernateSynchronizer(2.3.1 & 3.1.9)

    HibernateSynchronizer是开发者Hudson创建的一款工具,它的核心目标是帮助开发者快速生成符合Hibernate规范的Java实体类,同时能够根据数据库的变更自动更新这些实体类,使得代码与数据库保持一致。该工具支持与...

    HibernateSynchronizer的安装与使用

    通过自动生成 Hibernate 的配置文件(hibernate.cfg.xml)、映射文件(.hbm.xml)以及 Plain Object 类文件,HibernateSynchronizer 大大减少了手动编写这些文件的工作量,提高了开发效率。 安装 Hibernate...

    领域驱动设计C# 2008实现问题.设计.解决方案

    10.3.2 和synchronizer类同步 10.4 总结 第11章 客户会员管理系统 11.1 问题 11.2 设计 11.2.1 密码安全 11.2.2 设计客户会员管理系统 11.3 解决方案 11.3.1 客户会员管理系统领域模型类 11.3.2 客户会员...

    Eclipse Hibernate Synchronizer插件操作数据库

    在使用Eclipse Hibernate Synchronizer时,开发者可以快速地将数据库结构映射到Java持久化类(POJOs),同时也能将这些类反向同步到数据库中。这在进行敏捷开发和数据库频繁调整时非常有用,因为它允许你在设计阶段...

    hibernateSynchronizer

    【hibernateSynchronizer】是一个专为Eclipse开发的插件,它的主要功能是简化Hibernate项目的开发工作,特别是处理数据库对象与Java类之间的映射关系。通过这个插件,开发者能够快速、方便地自动生成`.hbm.xml`文件...

    com.hudson.hibernatesynchronizer_3.2.zip

    HibernateSynchronizer是一款基于Hibernate的数据库同步工具,它能够帮助开发者高效地管理数据库与Java实体类之间的同步问题,确保数据模型与数据库表结构的一致性。在版本3.2中,这款工具提供了更稳定和强大的功能...

    HibernateSynchronizer

    例如,当我们在开发过程中新增或修改了实体类,不再需要手动编写SQL脚本来更新数据库,只需通过HibernateSynchronizer,即可自动完成这一过程。同样,当数据库表结构发生变化,如添加字段、删除字段或者更改字段类型...

    HibernateSynchronizer-3.1.1

    1. **自动创建映射文件**:基于已有的Java实体类,Hibernate Synchronizer能自动生成对应的.hbm.xml映射文件,包含字段映射、主键定义、关联关系等信息。 2. **动态更新映射**:当Java类的属性、注解等发生变化时,...

    hibernate synchronizer

    除了映射文件,Hibernate Synchronizer还能生成对应的Java实体类,这些类包含了数据库表字段的属性,以及相关的getter和setter方法,方便进行数据库操作。 四、最佳实践与注意事项 4.1 定期同步 为确保代码与...

    hibernateSynchronizer与spring集成

    在整合Hibernate Synchronizer与Spring框架的过程中,我们主要关注的是如何让这两个强大的工具协同工作,以实现高效的数据持久化管理。Hibernate Synchronizer是一个用于自动更新Hibernate映射文件(.hbm.xml)的...

Global site tag (gtag.js) - Google Analytics