java - 信号量场景代码

标签 java multithreading semaphore

在这个场景中,我试图复制一个真实的 ATM 机用例,即。在电子银行自助终端,我们同时有四台 ATM,因此 4 个人(线程)可以同时进行交易。

为此,我使用信号量来实现线程限制,但我得到了不可预测的输出。

 package multithreadinglearning;

import java.time.LocalTime;
import java.util.Scanner;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Semaphore;

 public class ATMSemaphoreExample implements Runnable {

Semaphore sem = new Semaphore(4);
Scanner sc = new Scanner(System.in);
int balance = 1000;

Accounts a;
Accounts b;

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {

    ExecutorService exec = Executors.newFixedThreadPool(10);

    for (int i = 0; i <= 9; i++)
        exec.submit(new ATMSemaphoreExample());
}

@Override
public void run() {

    System.out.println(LocalTime.now() + ":" + Thread.currentThread() + " : acquiring lock...");
    System.out.println(LocalTime.now() + ":" + Thread.currentThread() + " : available Semaphore permits now: "
            + sem.availablePermits());

    try {
        sem.acquire();

        System.out.println(LocalTime.now() + ":" + Thread.currentThread() + " : got the permit...");
        System.out.println(LocalTime.now() + ":" + Thread.currentThread()
                + " : in available Semaphore permits now: " + sem.availablePermits());

        System.out.println("enter sender");
        String sender = sc.next();
        System.out.println("enter reciever");

        String reciver = sc.next();

        a = Bank.getAccount(sender);
        b = Bank.getAccount(reciver);

        System.out.println("a" + a);
        System.out.println("b" + b);

        System.out.println(LocalTime.now() + ":" + "i am " + Thread.currentThread() + "transafering money");

        System.out.println(LocalTime.now() + ":" + Thread.currentThread()
                + " :  inside available Semaphore permits now: " + sem.availablePermits());

        Thread.sleep(5000);
        Accounts.transfer(a, b, 1000);

        System.out.println("balance A:" + a.balance);
        System.out.println("balance B:" + b.balance);

        System.out.println(LocalTime.now() + ":" + Thread.currentThread() + " : releasing lock...");
        sem.release();
        System.out.println(LocalTime.now() + ":" + Thread.currentThread() + " : available Semaphore permits now: "
                + sem.availablePermits());
    } catch (InterruptedException | IllegalArgumentException | IllegalAccessException e) {

        e.printStackTrace();
    }
}
}

这是我得到的输出:

   11:46:39.888:Thread[pool-1-thread-2,5,main] : acquiring lock...
11:46:39.888:Thread[pool-1-thread-4,5,main] : acquiring lock...
11:46:39.888:Thread[pool-1-thread-1,5,main] : acquiring lock...
11:46:39.888:Thread[pool-1-thread-3,5,main] : acquiring lock...
11:46:39.888:Thread[pool-1-thread-9,5,main] : acquiring lock...
11:46:39.888:Thread[pool-1-thread-3,5,main] : available Semaphore permits 
 now: 4
11:46:39.888:Thread[pool-1-thread-7,5,main] : acquiring lock...
11:46:39.888:Thread[pool-1-thread-6,5,main] : acquiring lock...
11:46:39.888:Thread[pool-1-thread-10,5,main] : acquiring lock...
11:46:39.888:Thread[pool-1-thread-5,5,main] : acquiring lock...
11:46:39.889:Thread[pool-1-thread-10,5,main] : available Semaphore permits 
 now: 4
11:46:39.889:Thread[pool-1-thread-5,5,main] : available Semaphore permits 
 now: 4
11:46:39.888:Thread[pool-1-thread-8,5,main] : acquiring lock...
11:46:39.889:Thread[pool-1-thread-5,5,main] : got the permit...
11:46:39.889:Thread[pool-1-thread-10,5,main] : got the permit...
11:46:39.888:Thread[pool-1-thread-6,5,main] : available Semaphore permits 
 now: 4
11:46:39.888:Thread[pool-1-thread-7,5,main] : available Semaphore permits 
 now: 4
11:46:39.888:Thread[pool-1-thread-3,5,main] : got the permit...
11:46:39.888:Thread[pool-1-thread-9,5,main] : available Semaphore permits 
now: 4
11:46:39.888:Thread[pool-1-thread-1,5,main] : available Semaphore permits 
 now: 4
11:46:39.888:Thread[pool-1-thread-4,5,main] : available Semaphore permits 
 now: 4
11:46:39.888:Thread[pool-1-thread-2,5,main] : available Semaphore permits 
 now: 4
11:46:39.889:Thread[pool-1-thread-4,5,main] : got the permit...
11:46:39.889:Thread[pool-1-thread-1,5,main] : got the permit...
11:46:39.889:Thread[pool-1-thread-9,5,main] : got the permit...
11:46:39.889:Thread[pool-1-thread-3,5,main] : in available Semaphore permits 
 now: 3
11:46:39.889:Thread[pool-1-thread-7,5,main] : got the permit...
11:46:39.889:Thread[pool-1-thread-6,5,main] : got the permit...
11:46:39.889:Thread[pool-1-thread-7,5,main] : in available Semaphore permits 
 now: 3
enter sender
11:46:39.889:Thread[pool-1-thread-10,5,main] : in available Semaphore 
 permits now: 3
enter sender
11:46:39.889:Thread[pool-1-thread-5,5,main] : in available Semaphore permits 
now: 3
enter sender
11:46:39.889:Thread[pool-1-thread-8,5,main] : available Semaphore permits 
 now: 4
11:46:39.889:Thread[pool-1-thread-6,5,main] : in available Semaphore permits 
 now: 3
enter sender
enter sender
11:46:39.889:Thread[pool-1-thread-9,5,main] : in available Semaphore permits 
 now: 3
enter sender
11:46:39.889:Thread[pool-1-thread-1,5,main] : in available Semaphore permits 
 now: 3
enter sender
11:46:39.889:Thread[pool-1-thread-4,5,main] : in available Semaphore permits 
now: 3
enter sender
11:46:39.889:Thread[pool-1-thread-2,5,main] : got the permit...
11:46:39.889:Thread[pool-1-thread-8,5,main] : got the permit...
11:46:39.889:Thread[pool-1-thread-2,5,main] : in available Semaphore permits 
 now: 3
enter sender
11:46:39.889:Thread[pool-1-thread-8,5,main] : in available Semaphore permits 
now: 3
enter sender

在输出中,为什么所有线程都进入 run() 方法的业务代码并要求用户输入,而不是仅 4

最佳答案

每个可运行实例 (ATMSemaphoreExample) 都有自己的信号量。

Semaphore sem = new Semaphore(4);

它们对另一个线程没有任何影响。

将 sem 声明为静态类型,让所有线程使用同一个信号量实例。

private static Semaphore sem =  new Semaphore(4);

或从 main 传递信号量。

关于java - 信号量场景代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44582269/

相关文章:

java - 如何使用 springboot 和 logback 按严重性将日志记录分离到不同的文件

java - Eclipse 插件开发 : Listener for change of view of opened document

linux - 在 Linux 上使用信号与 POSIX 线程

java - 如何同步两个方法?

linux - 在 Linux 中控制信号量队列中的出队顺序

c - OSX/Ubuntu/Soliars 上的信号量行为不同,线程执行超出 sem_wait()

java - Mongodb 批量操作中的跟踪操作

java - JUnit - 空指针异常

c++ - 在 C++ 中终止线程的正确方法

c - 为什么与管道信号量的同步会以这种奇怪的方式表现?