[英]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.