zoukankan      html  css  js  c++  java
  • 泛型类的正确用法

    在准备下次直播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类)属性意外,针对需要引入新的属性的实践任务类,例如RequestThreadTimeUpdateSqlThread等多线程任务类中,额外的属性对象就可以用这个泛型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首发,原创分享爱好者,腾讯云、开源中国和掘金社区首页推荐,知乎八级强者,欢迎关注、交流,禁止第三方擅自转载。

    FunTester热文精选

  • 相关阅读:
    java用户角色权限设计
    六种方式实现hibernate查询,及IDE推荐
    SSH远程会话管理工具
    Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置
    Linux 下JDK安装
    linux下FTP的工具和使用以及rpmReadSignature failed错误
    不用FTP使用SecureCRT上传下载文件,并解决rz、sz command not found异常
    hibernate通过数据库表反向生成实体类
    解决vmware 桥联 再次使用联不上网的问题
    log4j详解与实战
  • 原文地址:https://www.cnblogs.com/FunTester/p/13856768.html
Copyright © 2011-2022 走看看