All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alibaba.mtc.MtContextCallable Maven / Gradle / Ivy
Go to download
a simple lib for transmitting context between thread even using thread pool.
package com.alibaba.mtc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;
/**
* {@link MtContextCallable} decorate {@link Callable}, so as to get {@link MtContextThreadLocal}
* and transmit it to the time of {@link Callable} execution, needed when use {@link Callable} to thread pool.
*
* Use factory method {@link #get(Callable)} to get decorated instance.
*
* @author ding.lid
* @see java.util.concurrent.Executor
* @see java.util.concurrent.ExecutorService
* @see java.util.concurrent.ThreadPoolExecutor
* @see java.util.concurrent.ScheduledThreadPoolExecutor
* @see java.util.concurrent.Executors
* @see java.util.concurrent.CompletionService
* @see java.util.concurrent.ExecutorCompletionService
* @since 0.9.0
*/
public final class MtContextCallable implements Callable {
private final AtomicReference, Object>> copiedRef;
private final Callable callable;
private final boolean releaseMtContextAfterCall;
private MtContextCallable(Callable callable, boolean releaseMtContextAfterCall) {
this.copiedRef = new AtomicReference, Object>>(MtContextThreadLocal.copy());
this.callable = callable;
this.releaseMtContextAfterCall = releaseMtContextAfterCall;
}
/**
* wrap method {@link Callable#call()}.
*/
@Override
public V call() throws Exception {
Map, Object> copied = copiedRef.get();
if (copied == null || releaseMtContextAfterCall && !copiedRef.compareAndSet(copied, null)) {
throw new IllegalStateException("MtContext is released!");
}
Map, Object> backup = MtContextThreadLocal.backupAndSet(copied);
try {
return callable.call();
} finally {
MtContextThreadLocal.restore(backup);
}
}
public Callable getCallable() {
return callable;
}
/**
* Factory method, wrapper input {@link Callable} to {@link MtContextCallable}.
*
* This method is idempotent.
*
* @param callable input {@link Callable}
* @return Wrapped {@link Callable}
*/
public static MtContextCallable get(Callable callable) {
return get(callable, false);
}
/**
* Factory method, wrapper input {@link Callable} to {@link MtContextCallable}.
*
* This method is idempotent.
*
* @param callable input {@link Callable}
* @param releaseMtContextAfterCall release MtContext after run, avoid memory leak even if {@link MtContextRunnable} is referred.
* @return Wrapped {@link Callable}
*/
public static MtContextCallable get(Callable callable, boolean releaseMtContextAfterCall) {
return get(callable, releaseMtContextAfterCall, false);
}
/**
* Factory method, wrapper input {@link Callable} to {@link MtContextCallable}.
*
* This method is idempotent.
*
* @param callable input {@link Callable}
* @param releaseMtContextAfterCall release MtContext after run, avoid memory leak even if {@link MtContextRunnable} is referred.
* @param idempotent is idempotent or not. {@code true} will cover up bugs! DO NOT set, only when you know why.
* @return Wrapped {@link Callable}
*/
public static MtContextCallable get(Callable callable, boolean releaseMtContextAfterCall, boolean idempotent) {
if (null == callable) {
return null;
}
if (callable instanceof MtContextCallable) {
if (idempotent) {
// avoid redundant decoration, and ensure idempotency
return (MtContextCallable) callable;
} else {
throw new IllegalStateException("Already MtContextCallable!");
}
}
return new MtContextCallable(callable, releaseMtContextAfterCall);
}
/**
* wrapper input {@link Callable} Collection to {@link MtContextCallable} Collection.
*
* @param tasks task to be wrapped
* @return Wrapped {@link Callable}
*/
public static List> gets(Collection extends Callable> tasks) {
return gets(tasks, false, false);
}
/**
* wrapper input {@link Callable} Collection to {@link MtContextCallable} Collection.
*
* @param tasks task to be wrapped
* @param releaseMtContextAfterCall release MtContext after run, avoid memory leak even if {@link MtContextRunnable} is referred.
* @return Wrapped {@link Callable}
*/
public static List> gets(Collection extends Callable> tasks, boolean releaseMtContextAfterCall) {
if (null == tasks) {
return null;
}
List> copy = new ArrayList>();
for (Callable task : tasks) {
copy.add(MtContextCallable.get(task, releaseMtContextAfterCall, false));
}
return copy;
}
/**
* wrapper input {@link Callable} Collection to {@link MtContextCallable} Collection.
*
* @param tasks task to be wrapped
* @param releaseMtContextAfterCall release MtContext after run, avoid memory leak even if {@link MtContextRunnable} is referred.
* @param idempotent is idempotent or not. {@code true} will cover up bugs! DO NOT set, only when you know why.
* @return Wrapped {@link Callable}
*/
public static List> gets(Collection extends Callable> tasks, boolean releaseMtContextAfterCall, boolean idempotent) {
if (null == tasks) {
return null;
}
List> copy = new ArrayList>();
for (Callable task : tasks) {
copy.add(MtContextCallable.get(task, releaseMtContextAfterCall, idempotent));
}
return copy;
}
}