繁体   English   中英

当任务通过执行器服务提交给线程池中的线程时,如何保证一次只能有1个线程占用一个同步任务?

[英]When task is submitted to threads in a thread pool via executor service how to ensure that only 1 thread can occupy a synchronized task at a time?

我有以下工人 class -

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()已经同步。 因此,当 1 个线程占用它时,另一个线程必须等到该线程离开锁。

但是当我使用 2 个线程的线程池提交工作时,两个线程似乎同时使用increment()

那么在这里我怎样才能强制两个线程一次只使用一个increment()方法呢?

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实例时作为参数传递。 这将阻止从同一个Boss创建的所有Worker实例(在这种方法中, lock是非静态的 object )。


  • 自带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 class作为锁来同步线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM