Using Java Generics to Simplify Multithreaded Task Design
This article explores how to apply Java generics in a multithreaded task framework, demonstrates refactoring a ThreadBase class, provides concrete code examples with RequestThreadTimes, and discusses the challenges and solutions for generic type constraints in inheritance hierarchies.
When preparing a live stream on Java basics, the author noticed the need to better use Java generics in a multithreaded testing framework. The original ThreadBase<T> class defined a generic field public T t;, but it was only used to store a string marker, offering little flexibility and causing lock issues.
To make the framework more extensible, the author proposes moving the generic type T into concrete task classes that require additional properties, such as RequestThreadTime and UpdateSqlThread. This allows each task subclass to specify the exact type of resource it works with.
The article then presents a full implementation of a concrete subclass RequestThreadTimes<T extends HttpRequestBase>. The class extends HttpRequestBase and ThreadLimitTimesCount<HttpRequestBase>, providing constructors, lifecycle hooks, and a clone method that copies the request object and optional mark.
package com.fun.frame.thead;
import com.fun.base.constaint.ThreadLimitTimesCount;
import com.fun.base.interfaces.MarkThread;
import com.fun.frame.httpclient.FanLibrary;
import com.fun.frame.httpclient.FunRequest;
import com.fun.frame.httpclient.GCThread;
import org.apache.http.client.methods.HttpRequestBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RequestThreadTimes<T extends HttpRequestBase> extends ThreadLimitTimesCount<HttpRequestBase> {
static Logger logger = LoggerFactory.getLogger(RequestThreadTimes.class);
public RequestThreadTimes(HttpRequestBase request, int times) {
super(request, times, null);
}
public RequestThreadTimes(HttpRequestBase request, int times, MarkThread mark) {
super(request, times, mark);
}
@Override
public void before() {
super.before();
GCThread.starts();
}
@Override
protected void doing() throws Exception {
FanLibrary.executeSimlple(t);
}
@Override
public RequestThreadTimes clone() {
RequestThreadTimes threadTimes = new RequestThreadTimes();
threadTimes.times = this.times;
threadTimes.t = FunRequest.cloneRequest(t);
threadTimes.mark = mark == null ? null : mark.clone();
return threadTimes;
}
}During experimentation, several class declarations were tried, such as omitting the generic bound or using raw types, which all produced compilation errors. The final successful declaration uses <T extends HttpRequestBase> to constrain the generic type, allowing the superclass constructor call super(request, times, mark) to compile correctly.
The article also shows an updated mark method that safely casts a ThreadBase instance to the appropriate subclass and retrieves the generic field t for marking.
@Override
public String mark(ThreadBase threadBase) {
if (threadBase instanceof RequestThreadTime) {
RequestThreadTime<HttpRequestBase> req = (RequestThreadTime<HttpRequestBase>) threadBase;
return mark(req.t);
} else if (threadBase instanceof RequestThreadTimes) {
RequestThreadTimes<HttpRequestBase> req = (RequestThreadTimes<HttpRequestBase>) threadBase;
return mark(req.t);
} else {
ParamException.fail(threadBase.getClass().toString());
}
return EMPTY;
}The complete source code is available at https://github.com/JunManYuanLong/FunTester , where readers can compare the before‑and‑after changes.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
