分享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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章