`

Concurrent - Semaphore - Semaphore(int permits)

 
阅读更多

原创转载请注明出处:http://agilestyle.iteye.com/blog/2342878

 

Semaphore所提供的功能完全是synchronized关键字的升级版,但它提供的功能更加的强大和方便,主要的作用是控制线程并发的数量

Semaphore(int permits)


 

设置permits为1

Service.java

package org.fool.java.concurrent.semaphore;

import java.util.concurrent.Semaphore;

public class Service {
    private Semaphore semaphore = new Semaphore(1);

    public void testMethod() {
        try {
            semaphore.acquire();

            System.out.println(Thread.currentThread().getName() + " begin timer=" + System.currentTimeMillis());

            Thread.sleep(5000);

            System.out.println(Thread.currentThread().getName() + " end timer=" + System.currentTimeMillis());

            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Note:

permits代表同一时间内,最多允许多少个线程同时执行acquire()和release()之间的代码。

本例设置为1,所以最多只有1个线程同时执行acquire()和release()之间的代码。

ThreadA.java

package org.fool.java.concurrent.semaphore;

public class ThreadA implements Runnable {
    private Service service;

    public ThreadA(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.testMethod();
    }
}

ThreadB.java

package org.fool.java.concurrent.semaphore;

public class ThreadB implements Runnable {
    private Service service;

    public ThreadB(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.testMethod();
    }
}

ThreadC.java

package org.fool.java.concurrent.semaphore;

public class ThreadC implements Runnable {
    private Service service;

    public ThreadC(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.testMethod();
    }
}

SemaphoreTest.java

package org.fool.java.concurrent.semaphore;

public class SemaphoreTest {
    public static void main(String[] args) {
        Service service = new Service();

        Thread a = new Thread(new ThreadA(service));
        Thread b = new Thread(new ThreadA(service));
        Thread c = new Thread(new ThreadA(service));

        a.setName("A");
        b.setName("B");
        c.setName("C");

        a.start();
        b.start();
        c.start();
    }
}

Run


Note:

private Semaphore semaphore = new Semaphore(1);

由于定义了最多1个线程执行acquire()和release()之间的代码,所以打印的结果就是3个线程是同步的,线程A执行结束的时间和线程B执行开始的时间相同,线程B执行结束的时间和线程C还行开始的时间相同。

 

修改Service.java,设置permits为2

private Semaphore semaphore = new Semaphore(2);

再次Run SemaphoreTest


Note:

由于定义了最多2个线程执行acquire()和release()之间的代码,所以线程A和线程B执行开始的时间是相同的,需要注意的是,对Semaphore的构造方法传递的参数permits值如果大于1时,该类并不能保证线程的安全性,因为还是有可能会出现多个线程共同访问实例变量,导致出现脏读。

 

Semaphore(int permits, boolean fair)

有些时候,获得permits的顺序与线程启动的顺序有关,这时信号量就要分为公平和非公平的。

公平信号量是获得锁的顺序与线程启动的顺序有关,但不代表100%地获得信号量,仅仅是在概率上能得到保证。

非公平信号量即获得锁的顺序与线程启动的顺序无关。

Service.java

package org.fool.java.concurrent.semaphore.fair;

import java.util.concurrent.Semaphore;

public class Service {
    private boolean isFair = false;
    private Semaphore semaphore = new Semaphore(1, isFair);

    public void testMethod() {
        try {
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
        }
    }
}

Note:

设置了非公平信号量

private boolean isFair = false;

 

ThreadA.java

package org.fool.java.concurrent.semaphore.fair;

public class ThreadA implements Runnable {
    private Service service;

    public ThreadA(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " invoked...");
        service.testMethod();
    }
}

FairTest.java

package org.fool.java.concurrent.semaphore.fair;

public class FairTest {
    public static void main(String[] args) {
        Service service = new Service();

        Thread a = new Thread(new ThreadA(service));
        a.start();

        for(int i = 0; i < 4; i++) {
            new Thread(new ThreadA(service)).start();
        }
    }
}

 

Run

非公平信号量运行的效果是线程启动的顺序与调用semaphore.acquire()的顺序无关,也就是线程先启动了并不代表获得permits


 

修改Service.java,设置公平信号量

private boolean isFair = true;

 

再Run

公平信号量运行的效果是线程启动的顺序与调用semaphore.acquire()的顺序有关,也就是先启动的线程优先获得permits

 

 

 

 

 

 

 

  • 大小: 13.7 KB
  • 大小: 17.7 KB
  • 大小: 17.4 KB
  • 大小: 19 KB
  • 大小: 18.7 KB
分享到:
评论

相关推荐

    通俗易懂学习java并发工具类-Semaphore,Exchanger

    【Semaphore详解】Semaphore是Java并发包`java.util.concurrent`中的一个工具类,它主要用于控制并发访问的线程数量。Semaphore可以被理解为一种资源的许可证,每个许可证代表了一个可访问的资源实例。线程在执行前...

    JAVA多线程--信号量(Semaphore)_.docx

    Semaphore(int permits, boolean fair) ``` 创 建 具 有 给 定 的 许 可 数 和 给 定 的 公 正 设 置 的Semaphore。 Semaphore当前在多线程环境下被扩放用法,操作系统的信号量是个很重要的概念,在进程掌握方面都...

    Java 信号量编程实践

    2. `Semaphore(int permits, boolean fair)`:创建具有指定初始许可数的信号量,并可以选择是否采用公平策略。公平策略意味着等待时间最长的线程将优先获取许可,而不公平策略则没有这样的保证。 **二、Semaphore的...

    并发编程之Tools&CountDownLatch&Semaphore原理与应用1

    2. `Semaphore(int permits, boolean fair)`:除了指定许可数量外,还可以设置是否启用公平策略。公平策略意味着等待最长时间的线程优先获得许可。 Semaphore提供以下核心方法: 1. `void acquire()`:获取一个...

    Java并发编程之Semaphore(信号量)详解及实例

    2. `Semaphore(int permits, boolean fair)`: 创建具有给定许可数的公平(true)或非公平(false)Semaphore。 Semaphore 的方法 1. `acquire()`: 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则...

    Java进程信号量机制的实验程序

    - `Semaphore(int permits)`构造函数初始化信号量,参数`permits`表示初始的许可数量。 - `acquire()`方法用于获取一个许可,如果当前许可数量大于零,则消耗一个许可,否则线程被阻塞等待。 - `acquire(int ...

    Java并发编程(23)并发新特性-信号量Semaphor

    在Java 5引入并发包`java.util.concurrent`后,信号量作为`Semaphore`类被添加,成为并发编程的一个新特性。 信号量的核心概念是许可(permits),它可以看作是系统中可用资源的数量。当一个线程想要访问公共资源时...

    Java基于Semaphore构建阻塞对象池

    1. `Semaphore(int permits)`:默认是非公平策略,创建一个具有指定许可数量的Semaphore。 2. `Semaphore(int permits, boolean fair)`:允许指定是否采用公平策略。公平策略意味着按照线程等待的顺序分配许可,而非...

    JAVA 多线程之信号量(Semaphore)实例详解

    Semaphore(int permits, boolean fair) // 创建指定数量的许可证的信号量,并指定是否为公平模式 ``` ### 代码示例 下面是一个简单的Semaphore使用示例,模拟了5个资源(停车位)供20个线程(车辆)共享的情况: ...

    米哈游笔试题目-Java方向.docx

    this.semaphore = new Semaphore(permits); } public void acquire() throws InterruptedException { semaphore.acquire(); } public void release() { semaphore.release(); } } ``` ### 分布式锁类 ##...

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解

    public Semaphore(int permits);//参数permits表示可用的许可数 Semaphore类中最重要的三个方法是: 1. public void acquire() throws InterruptedException {}; //获得一个许可 2. public boolean tryAcquire() ...

    SOI-ThreadsSemaphore-I

    在Java编程语言中,`Semaphore`是一个非常重要的同步工具类,它源于`java.util.concurrent`包,用于控制同时访问特定资源的线程数量。标题"SOI-ThreadsSemaphore-I"暗示了这个项目或教程可能专注于如何在多线程环境...

    semaphores:一个简单的信号量程序,显示当多个线程尝试同时访问代码的关键部分时如何互斥

    5. `tryAcquire(int permits)`: 尝试获取指定数量的许可证。如果足够数量的许可证可用,立即返回true;否则,返回false。 在实际应用中,信号量常用于限制线程池大小、保护临界区或实现线程之间的协作。例如,在一...

    java线程通信课程设计

    首先,我们需要了解Java中实现线程通信的关键类和接口,如`Object`类的`wait()`、`notify()`和`notifyAll()`方法,以及`java.util.concurrent`包下的`BlockingQueue`、`Semaphore`、`CyclicBarrier`等工具类。...

Global site tag (gtag.js) - Google Analytics