分享java压力测试模版类 版本2

        在上一次,我们分享了一个压力测试的模板类,在模板类里面通过继承然后实现重写几个方法即可以实现压力测试,其本质就是由实现者去实现具体的测试逻辑,将功能代码独立抽离出来实现复用。然而,继承存在着一些缺点是无法避免的。比如具体的失去了灵活性,而且如果java不支持多继承,意味着测试类会被限制少了继承其他类的能力,再者之前的代码对外部暴露的接口过多,无法对用户实现彻底的透明。因此对原先的代码采用了Function方式进行重构。

        Function的方式即将函数作为参数传入方法中,由具体的调用者去决定函数的内容,这个刚好是我们需要的,由具体的测试者去实现需要测试的逻辑。可惜在java中并不支持将函数作为参数传入方法中,不能像js那样  function xxx(functionx)去声明调用。不过,在设计模式中有一种叫做命令模式的,我们简单的借用下。

       

public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

        在java的java.util下有这个Runable的接口,只需要实现run方法即可。

public void xxx(Runable r){
        r.run();
}
        如果有疑问function不是一个接口吗,那apply方法哪里实现的,这样想就对了。如果要体会这种写法怎么做,可以直接new Function()xxxx看看IDE会怎么帮你自动生成一些代码。这个就是由调用xxx的用户去实现function的内容,在运行该方法的处决定function接口的内容,将实现者和调用者解耦。
       接下来是重构过的测试模板类。正确的说不是模板类了,是直接可以运行的功能类了。

       



import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;  
import java.util.concurrent.atomic.AtomicLong;  
  
  
/** 
 * 通用压力测试类 
 * Created by lsz on 14-10-24. 
 */  
public class CommonsTest {  
    int threadNum = 1;  
    int sleepTime = 1000;  
    long lastTimes = 0;  
    int x = 0;  
    private AtomicLong now = new AtomicLong();  
    private AtomicLong maxTime = new AtomicLong(0l);  
    ExecutorService pool = null;  
    Runnable runnable;
  
    public CommonsTest(int threadNum,Runnable runnable) {
        this.runnable = runnable;
        this.threadNum = threadNum;  
        pool = Executors.newScheduledThreadPool(this.threadNum);  
  
    }  
    CommonsTest(int threadNum){  
        this(threadNum,null);  
    }  
    CommonsTest(Runnable runnable){
        this(5,runnable);
    }  
  
    public static CommonsTest create(){  
        return new CommonsTest(5);  
    }  
    public CommonsTest setThreadNum(int threadNum){  
        this.threadNum = threadNum;  
        return this;  
    }  
    public CommonsTest setApply(Runnable runnable){
        this.runnable = runnable;
        return this;
    }  
  
    public void start(){  
        for(int i = 0 ; i<threadNum;i ++ ){  
            pool.execute(new TestThread());  
        }  
        String format = "---------------------"+"当前1s内的执行数"+"/"+"总的执行数"+"/"+"平均的执行数"+"/"+"执行的时间"+"/"+"最长执行时间";  
        while(true){  
            try {  
                x++;  
                Thread.sleep(sleepTime);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            long nowtmp = now.get();  
            System.out.println(format);  
            System.out.println("---------------------"+(nowtmp - lastTimes)+"/"+now.intValue()+"/"+(now.intValue()/x)+"/"+x+"/"+maxTime.get()+"ms");  
            lastTimes = nowtmp;  
        }  
    }  
  
    class TestThread extends Thread{  
        public TestThread() {  
  
        }  
        @Override  
        public void run() {  
            System.out.println("start------------------"+Thread.currentThread().getName());  
            while (true){  
                try {  
                    long start = System.currentTimeMillis();
                    runnable.run();
                    long end = System.currentTimeMillis() - start;
                    if(end>maxTime.get()){  
                        maxTime.set(end);  
                    }  
                    now.incrementAndGet();  
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
  
            }  
        }
    }  
}

         看到这个类,感觉和之前的模板类没啥区别,只是在具体的测试代码调用处从模版方法改成了接口方法。具体的使用也简单了n多。

/**
 * Created by lsz on 14-10-24.
 */
public class SimpleTest {
    public static void main(String[] args) {
        new CommonsTest(5,new Runable() {
            @Override
            public void run {
                //这里写压力测试的逻辑代码
                // 创建http请求(get方式)
                // HttpGet httpget = new HttpGet("http://www.xxx.com/xxx");
                //httpclient.execute(httpget);
                return true;
            }
        }).start();
    }
}

          在这里只需要关心线程数和业务逻辑了,不需要继承任何类,欢迎讨论。





发布了52 篇原创文章 · 获赞 15 · 访问量 20万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章