我有以下工人阶级-
public class Worker implements Runnable {
private int workId;
public Worker(int workId) {
this.workId = workId;
}
private int count = 0;
private synchronized void increment() {
System.out.println("Work id: " + workId);
System.out.println("Incrementing...");
Thread.sleep(5000);
count++;
System.out.println("Incremented");
}
@Override
public void run() {
increment();
}
}
我有以下主要方法-
ExecutorService executorService = Executors.newFixedThreadPool(2);
for (int i = 1; i <= 10; i++) {
executorService.submit(new Worker(i));
}
executorService.shutdown();
System.out.println("All tasks submitted");
executorService.awaitTermination(1, TimeUnit.DAYS);
System.out.println("All tasks completed");
在这里 increment()
已同步。因此,当一个线程占用它时,另一个线程必须等待该线程离开锁。
但是当我使用2个线程的线程池提交工作时,两个线程似乎都在使用 increment()
同时。
那么在这里我如何强制两个线程使用 increment()
一次只能用一种方法?
1条答案
按热度按时间kx5bkwkv1#
这种方法在
Object
级别,因此如果您有两个对象,它们在调用此对象时不会相互阻塞,因为每个对象都会调用自己的对象increment()
方法(没有对同一Worker
示例)。为了避免不同的示例访问
increment()
方法,您需要在Class
级别,该级别在所有用户的锁相同时实现Worker
示例。声明锁的一些选项:共享
Object
```public class Boss extends RichDad implements EarnLotsOfMoney
{
private final Object masterLock;
public Boss()
{
masterLock = new Object();
}
public Worker createWorker(int slaveId)
{
return new Worker(masterLock, slaveId);
}
//...
}
public class Worker implements Runnable
{
private final Object lock;
private int workId;
public Worker(Object lock, int workId)
{
this.lock = lock;
this.workId = workId;
}
private void increment()
{
synchronized(lock) /lock holds the same reference in all instances/
{
//...
}
}
@Override
public void run() {
increment();
}
}
`lock` 只创建一次,然后在创建 `Worker` 示例。这将阻止所有 `Worker` 从同一个示例创建的示例 `Boss` (在这种方法中 `lock` 是非静态对象)。 它自己的 `Class`
public class Worker implements Runnable
{
private int workId;
public Worker(int workId) {
this.workId = workId;
}
private int count = 0;
private void increment()
{
synchronized(Worker.class) /class level lock here/
{
System.out.println("Work id: " + workId);
System.out.println("Incrementing...");
Thread.sleep(5000);
count++;
System.out.println("Incremented");
}
}
@Override
public void run() {
increment();
}
}