All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.funtom.util.concurrent.PerKeySynchronizedExecutor Maven / Gradle / Ivy

There is a newer version: 0.2
Show newest version
package io.funtom.util.concurrent;

import java.util.concurrent.locks.Lock;
import java.util.function.Supplier;

/**
 * An Executor which executes tasks on the caller thread.
 * The tasks will be executed synchronously on a per-key basis.
 * By saying per-key, we mean that thread safety is guaranteed for threads calling it with equals keys.
 * When two threads calling the executor with equals keys, the executions will never overlap each other.
 * On the other hand, the executor is implemented so calls from different threads, with keys that are not equals, will be executed concurrently with minimal contention between the calls.
 * Calling threads might be suspended.
 * Calling execute from different thread with equals keys has the same memory semantics as locking and releasing a java.util.concurrent.locks.{@link Lock}.
 */
public final class PerKeySynchronizedExecutor {

    private static final int CONCURRENCY_LEVEL = 32;

    private final ConcurrencySegment[] segments;

    @SuppressWarnings({"unchecked"})
    public PerKeySynchronizedExecutor() {
        segments = (ConcurrencySegment[]) new ConcurrencySegment[CONCURRENCY_LEVEL];
        for (int i = 0; i < CONCURRENCY_LEVEL; i++) {
            segments[i] = new ConcurrencySegment<>(SynchronizedExecutor::new);
        }
    }

    public void execute(KEY_TYPE key, Runnable task) {
        int segmentIndex = HashUtil.boundedHash(key, CONCURRENCY_LEVEL);
        ConcurrencySegment s = segments[segmentIndex];
        SynchronizedExecutor executor = s.getValue(key);
        try {
            executor.execute(task);
        } finally {
            s.releaseKey(key);
        }
    }

    public  R execute(KEY_TYPE key, Supplier task) {
        int segmentIndex = HashUtil.boundedHash(key, CONCURRENCY_LEVEL);
        ConcurrencySegment s = segments[segmentIndex];
        SynchronizedExecutor executor = s.getValue(key);
        try {
            return executor.execute(task);
        } finally {
            s.releaseKey(key);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy