在准备下次直播Java
基础的内容中,偶然看到Java泛型
这个知识点,突然有了点想法,之前一直纠结的一个问题有了解答的思路。
问题:我在多线程任务基类中定义了一个泛型T
的对象t
,但是一直没有找到一个特别合适的发光点,感觉跟重新写一个内部类差别不大,偶尔在匿名类中使用,非但没有更加灵活,反而衍生出一些其他多线程锁的问题。
具体代码如下:
完整的代码地址:https://github.com/JunManYuanLong/FunTester
public abstract class ThreadBase<T> extends SourceCode implements Runnable {
····省略代码···
/**
* 用于设置访问资源,用于闭包中无法访问包外实例对象的情况
* @since 2020年10月19日,统一用来设置HTTPrequestbase对象.同样可以用于执行SQL和redis查询语句或者对象,暂未使用dubbo尝试
*/
public T t;
这个t
对象在之前唯一用到的地方就是在标记执行任务的时候用到,把生成的标记(通常是String
类型)赋值到t
中,然后在接下来的过程中访问。但是也仅仅是多了一个存储的地方,实际上标记对象的方法会把标记返回。
突然想到的解决之道是,在除去几种基本类型的多线程任务类(多位abstract
类)属性意外,针对需要引入新的属性的实践任务类,例如RequestThreadTime
、UpdateSqlThread
等多线程任务类中,额外的属性对象就可以用这个泛型T
代替。
突觉自己以前走了很多弯路,对泛型的掌握和应用太浅薄,说干就干了,马上对现有的性能测试框架中的abstract
类和实现类都改一遍。
这里取RequestThreadTimes
为例分享一下代码,有兴趣的同学可以在GitHub
上看到我的提交记录,对比一下前后的修改。
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;
/**
* http请求多线程类
*/
public class RequestThreadTimes<T extends HttpRequestBase> extends ThreadLimitTimesCount<HttpRequestBase> {
static Logger logger = LoggerFactory.getLogger(RequestThreadTimes.class);
/**
* 单请求多线程多次任务构造方法
*
* @param request 被执行的请求
* @param times 每个线程运行的次数
*/
public RequestThreadTimes(HttpRequestBase request, int times) {
super(request, times, null);
}
/**
* 应对对每个请求进行标记的情况
*
* @param request
* @param times
* @param mark
*/
public RequestThreadTimes(HttpRequestBase request, int times, MarkThread mark) {
super(request, times, mark);
}
protected RequestThreadTimes() {
super();
}
@Override
public void before() {
super.before();
GCThread.starts();
}
/**
* @throws Exception
*/
@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;
}
}
关于类名那一行,我尝试了很多中办法,包括public class RequestThreadTimes<T extends HttpRequestBase> extends ThreadLimitTimesCount<HttpRequestBase> {
、public class RequestThreadTimes<T> extends ThreadLimitTimesCount<HttpRequestBase> {
、public class RequestThreadTimes extends ThreadLimitTimesCount<HttpRequestBase> {
、public class RequestThreadTimes<HttpRequestBase> extends ThreadLimitTimesCount<HttpRequestBase> {
,然后报出了各种错误,最终我选择了第一种写法,据我粗浅的尝试,被继承的父类中T
可以声明成为HttpRequestBase
类,然后在代码中关于父类的操作,如super(request, times, mark);
中是可以成立的,然后在本类名后面的泛型不能声明对象,只能用<T extends HttpRequestBase>
限制创建对象是声明泛型的上限。
这里还涉及到一个标记方法中类型转化的修改,如下:
@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;
}
公众号FunTester首发,原创分享爱好者,腾讯云、开源中国和掘金社区首页推荐,知乎八级强者,欢迎关注、交流,禁止第三方擅自转载。