当任务通过执行器服务提交给线程池中的线程时,如何确保一次只能有一个线程占用一个同步任务?
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
是一个非静态对象).
自己的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 作为锁来同步线程。
我有以下工作人员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
是一个非静态对象).
自己的
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 作为锁来同步线程。