当任务通过executor服务提交到线程池中的线程时,如何确保一次只有一个线程可以占用同步的任务?

m1m5dgzv  于 2021-06-26  发布在  Java
关注(0)|答案(1)|浏览(464)

我有以下工人阶级-

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() 一次只能用一种方法?

kx5bkwkv

kx5bkwkv1#

private synchronized void increment()

这种方法在 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();
}
}

这将使用共享的 `Worker` 类为锁。

相关问题