在这个场景中,我试图复制一个真实的 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/