`

java多线程之Semaphore使用

阅读更多

        本文将介绍用来控制资源同时访问个数的Semaphore工具类,然后采用Semaphore给出一个泊车的实例,最后给出Semaphore和CountDownLatch的几点比较。

一. Semaphore工具类介绍

/**
 * A counting semaphore.  Conceptually, a semaphore maintains a set of
 * permits.  Each {@link #acquire} blocks if necessary until a permit is
 * available, and then takes it.  Each {@link #release} adds a permit,
 * potentially releasing a blocking acquirer.
 * However, no actual permit objects are used; the <tt>Semaphore</tt> just
 * keeps a count of the number available and acts accordingly.
 *
 * <p>Semaphores are often used to restrict the number of threads than can
 * access some (physical or logical) resource.
 */

        从Semaphore的注释中可以看出如下几点:
        1.从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。
        2. Semaphore并不使用实际的许可对象,Semaphore 只对可用许可进行计数,并采取相应的行动。

        3.Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。

        Semaphore中定义了一个内部类Sync,该类继承AbstractQueuedSynchronizer。从代码中可以看出,Semaphore的方法基本上都调用了Sync的方法来实现。Smaphore还提供了公平和非公平的两种方式。

        Semaphore工具类相关的类图如下:

 

二. Semaphore工具类的使用案例

        下面给出的示例模拟30辆车去泊车,而车位有10个的场景。当车位满时,出来一辆车,才能有一辆车进入停车。

Car.java

package my.concurrent.semaphore;

import java.util.concurrent.Semaphore;

public class Car implements Runnable {

    private final Semaphore parkingSlot;
    private int carNo;

    /**
     * @param parkingSlot
     * @param carName
     */
    public Car(Semaphore parkingSlot, int carNo) {
        this.parkingSlot = parkingSlot;
        this.carNo = carNo;
    }

    public void run() {
        try {
            parkingSlot.acquire();
            parking();
            sleep(300);
            parkingSlot.release();
            leaving();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void parking() {
        System.out.println(String.format("%d号车泊车", carNo));
    }

    private void leaving() {
        System.out.println(String.format("%d号车离开车位", carNo));
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ParkingCars.java

package my.concurrent.semaphore;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class ParkingCars {

    private static final int NUMBER_OF_CARS = 30;
    private static final int NUMBER_OF_PARKING_SLOT = 10;

    public static void main(String[] args) {
        /*
         * 采用FIFO, 设置true
         */
        Semaphore parkingSlot = new Semaphore(NUMBER_OF_PARKING_SLOT, true);
        ExecutorService service = Executors.newCachedThreadPool();
        for (int carNo = 1; carNo <= NUMBER_OF_CARS; carNo++) {
            service.execute(new Car(parkingSlot, carNo));
        }
        sleep(3000);
        service.shutdown();
        /*
         * 输出还有几个可以用的资源数
         */
        System.out.println(parkingSlot.availablePermits() + " 个停车位可以用!");
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

        运行结果:

4号车泊车
6号车泊车
8号车泊车
2号车泊车
10号车泊车
3号车泊车
5号车泊车
11号车泊车
1号车泊车
9号车泊车
4号车离开车位
13号车泊车
8号车离开车位
7号车泊车
2号车离开车位
15号车泊车
10号车离开车位
17号车泊车
6号车离开车位
12号车泊车
3号车离开车位
16号车泊车
14号车泊车
18号车泊车
11号车离开车位
5号车离开车位
1号车离开车位
19号车泊车
20号车泊车
9号车离开车位
13号车离开车位
21号车泊车
22号车泊车
7号车离开车位
15号车离开车位
23号车泊车
17号车离开车位
24号车泊车
12号车离开车位
25号车泊车
26号车泊车
14号车离开车位
27号车泊车
28号车泊车
16号车离开车位
20号车离开车位
29号车泊车
18号车离开车位
30号车泊车
19号车离开车位
21号车离开车位
23号车离开车位
22号车离开车位
26号车离开车位
24号车离开车位
28号车离开车位
30号车离开车位
25号车离开车位
27号车离开车位
29号车离开车位
10 个停车位可以用!

 

三. Semaphore vs. CountDownLatch

相同点:   
        两者都是用于线程同步的工具类,都通过定义了一个继承AbstractQueuedSynchronizer的内部类Sync来实现具体的功能。

不同点:
        1.Semaphore提供了公平和非公平两种策略, 而CountDownLatch则不具备。
        2.CountDownLatch: 一个或者是一部分线程,等待另外一部线程都完成操作。
           Semaphorr:维护一个许可集.通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。

        3.CountDownLatch中计数是不能被重置的。CountDownLatch适用于一次同步。当使用CountDownLatch时,任何线程允许多次调用countDown()。那些调用了await()方法的线程将被阻塞,直到那些没有被阻塞线程调用countDown()使计数到达0为止。
        Semaphore允许线程获取许可, 未获得许可的线程需要等待.这样防止了在同一时间有太多的线程执行.Semaphore的值被获取到后是可以释放的,并不像CountDownLatch那样一直减到0。

        4.使用CountDownLatch时,它关注的一个线程或者多个线程需要在其它在一组线程完成操作之后,在去做一些事情。比如:服务的启动等。使用Semaphore时,它关注的是某一个资源最多同时能被几个线程访问。

 

文章来源:http://mouselearnjava.iteye.com/blog/1921468

  • 大小: 26.3 KB
分享到:
评论

相关推荐

    java多线程经典案例

    通过分析并实践`threadTest`案例,我们可以深入理解Java多线程的原理和使用技巧,为编写高效并发程序打下坚实基础。同时,也要注意多线程编程中的死锁、活锁和饥饿等问题,合理设计线程间的交互,避免出现不可预期的...

    java多线程查询数据库

    综上所述,"java多线程查询数据库"是一个涉及多线程技术、线程池管理、并发控制、分页查询等多个方面的复杂问题。通过理解和掌握这些知识点,我们可以有效地提高数据库操作的效率和系统的响应速度。

    汪文君JAVA多线程编程实战(完整不加密)

    《汪文君JAVA多线程编程实战》是一本专注于Java多线程编程的实战教程,由知名讲师汪文君倾力打造。这本书旨在帮助Java开发者深入理解和熟练掌握多线程编程技术,提升软件开发的效率和质量。在Java平台中,多线程是...

    Java多线程Semaphore工具的使用详解.rar

    Java多线程编程是开发高并发应用的关键技术之一,Semaphore工具是Java并发包(java.util.concurrent)中的一个重要组件,用于控制同时访问特定资源的线程数量。本篇将深入讲解Semaphore的基本概念、工作原理以及如何...

    java多线程进度条

    本主题将深入探讨如何在Java多线程环境下实现进度条功能。 首先,理解Java多线程的基本概念至关重要。Java通过Thread类和Runnable接口来支持多线程。创建一个新线程通常有两种方式:继承Thread类并重写run()方法,...

    JAVAJAVA多线程教学演示系统论文

    《JAVA多线程教学演示系统》是一篇深入探讨JAVA多线程编程的论文,它针对教育领域中的教学需求,提供了一种生动、直观的演示方式,帮助学生更好地理解和掌握多线程技术。这篇论文的核心内容可能包括以下几个方面: ...

    JAVA多线程练习题答案。

    JAVA多线程练习题答案详解 在本文中,我们将对 JAVA 多线程练习题的答案进行详细的解释和分析。这些题目涵盖了 JAVA 多线程编程的基本概念和技术,包括线程的生命周期、线程同步、线程状态、线程优先级、线程安全等...

    Java多线程编程核心技术_完整版_java_

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过继承Thread类或实现Runnable接口来实现。本教程《Java多线程编程核心技术》将...

    Java多线程编程实战指南-核心篇

    《Java多线程编程实战指南-核心篇》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握在Java环境中创建、管理和同步线程的核心技术。Java的多线程能力是其强大之处,使得开发者能够在同一时间执行多个任务,提高...

    Java多线程下载器

    Java多线程下载器是一种利用Java编程语言实现的高效文件下载工具,它通过将大文件分割成多个部分并同时下载,显著提高了下载速度。在Java中实现多线程下载器涉及许多关键概念和技术,包括线程、并发控制、网络I/O...

    java多线程设计

    本知识点将深入探讨Java多线程设计以及如何利用“不可变对象”(immutable objects)来避免多线程环境中的非安全问题。 一、Java多线程基础 1. 线程的创建:Java提供了两种创建线程的方式——继承Thread类和实现...

    Java 多线程 PPT

    本文将深入探讨Java多线程的相关概念、线程类和接口的使用,以及线程的同步与互斥。 首先,我们需要理解进程与线程的基本概念。程序是一组静态指令的集合,而进程则是程序在执行过程中的一个实例,拥有独立的内存...

    Java多线程编程

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过`Thread`类和并发工具来实现,接下来我们将深入探讨这些关键知识点。 1. **...

    Java多线程设计模式_清晰完整PDF版 Java多线程设计模式源代码

    总之,Java多线程设计模式是每个Java开发者必备的技能之一。深入学习并熟练运用这些模式,将有助于你编写出更高效、稳定和易于扩展的多线程应用程序。这个PDF版教程和源代码集合是你学习多线程设计模式的理想资源,...

    java多线程进度条实例

    在Java编程中,多线程是一项关键特性,它允许程序同时执行多个任务,极大地提高了效率。本实例将探讨如何利用Java实现一个具有进度条显示功能的多线程应用。进度条通常用于可视化地表示某个任务的完成程度,这对于长...

    java多线程示例

    在Java编程语言中,多线程是核心特性之一,它允许程序同时执行多个任务,从而提高了应用程序的效率和响应...文档“java多线程实例.docx”可能包含具体的示例代码和详细解释,建议参考学习,以加深对Java多线程的理解。

    java多线程之并发锁

    Java 多线程之并发锁 Java 中的多线程编程是指在一个程序中同时运行多个线程,以提高程序的执行效率和响应速度。在多线程编程中,线程间的同步是非常重要的,因为不同的线程可能会同时访问同一个共享资源,导致数据...

    java 多线程简易聊天 精简版

    综上所述,这个“java 多线程简易聊天 精简版”项目涵盖了Java多线程编程的诸多核心概念,包括线程创建、网络通信、同步与互斥、异常处理以及IDE的使用。对于希望深入学习Java多线程编程的开发者来说,这是一个很好...

    java多线程小汽车运行程序

    总之,Java多线程技术是开发高并发应用程序的基础,熟练掌握线程的创建、同步、通信以及并发工具的使用,对于提升程序性能和解决复杂问题具有重要意义。这个"java多线程小汽车运行程序"为学习和实践这些概念提供了一...

    精通java多线程

    Java多线程是Java编程语言中的一个重要特性,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在现代计算机系统中,多核处理器的普及使得多线程技术成为提升性能的关键手段。本篇将深入探讨Java多线程...

Global site tag (gtag.js) - Google Analytics