国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java高并發及測試代碼

waruqi / 2952人閱讀

摘要:公司的妹子不會做并發測試。并發測試是多個人同時訪問一個服務,這不就是多線程嗎于是靈光一現使用多線程來寫并發測試代碼。測試得出如下代碼的執行效率最高,個并發耗時毫秒

公司的妹子不會做并發測試。做完一名程序猿看著有點干捉急。并發測試是多個人同時訪問一個服務,這不就是多線程嗎!于是靈光一現使用多線程來寫并發測試代碼。想想心理都有點小激動咧。效果比工具還好,廢話不多說貼代碼

添加Maven依賴

com.squareup.okhttp3
okhttp
3.8.1


com.squareup.okio
okio
1.11.0

com.google.code.gson
gson
2.8.0

先封裝OKHTTP(使用CallBack思想做的封裝),這個很早之前就封裝了,公司移動端也是使用OKHTTP做的服務請求調用。經常遇到圖片上傳不了的問題,報的錯是Socket連接超時的問題。解決這個問題so easy,把連接時間(KEEP_ALIVE)時間設置長一點就行了嘛!
OkHttp底層是用socket做的通信,現在很多應該的底層通信都用的Socket,例子不多說,全靠經驗。

public abstract class HttpCommon {

/**
 * 設置連接超時時間為30000秒
 */
private final static int CONNECT_TIMT_OUT = 30000;

/**
 * 設置寫超時時間為30000秒
 */
private final static int WRITE_TIME_OUT = 30000;


static {
    final OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder();
    okHttpClient = httpBuilder.connectTimeout(CONNECT_TIMT_OUT, TimeUnit.SECONDS)
            .writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS).build();

}

public abstract void callBack(String responseString);


/**
 * get請求
 *
 * @param url url地址
 * @param map 請求參數
 * @return 返回結果。如果為“”表示失敗
 */
public void get(String url, Map map) {

    url = wrapUrl(url, map);

    // 創建請求參數
    Request request = new Request.Builder().url(url).build();

    //創建請求對象
    Call call = okHttpClient.newCall(request);

    try {
        Response response = call.execute();
        if (response.isSuccessful()) {
            callBack(response.body().string());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * post請求
 *
 * @param url post請求的url
 * @param t   post請求的表單實體
 * @return 返回結果。如果為“”表示失敗
 */
public  void post(String url, Map map, T t) {
    url = wrapUrl(url, map);

    String json = new Gson().toJson(t);
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder().url(url).post(body).build();

    Response response = null;
    try {
        response = okHttpClient.newCall(request).execute();
        if (response.isSuccessful()) {
            callBack(response.body().string());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}


/**
 * post請求
 *
 * @param url post請求的url
 * @param t   post請求的表單實體
 * @return 返回結果。如果為“”表示失敗
 */
public  void post(String url, T t) {
    String json = new Gson().toJson(t);
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder().url(url).post(body).build();

    Response response = null;
    try {
        response = okHttpClient.newCall(request).execute();
        if (response.isSuccessful()) {
            callBack(response.body().string());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}


/**
 * 上傳文件請求
 *
 * @param url      請求url
 * @param map      請求參數
 * @param filePath 文件路徑
 * @return 返回結果。結果為""表示失敗
 */
private void uploadFile(String url, Map map, String filePath) {
    url = wrapUrl(url, map);

    File file = new File(filePath);
    RequestBody fileBody = RequestBody.create(OCTET, file);
    RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
            .addFormDataPart("image", file.getName(), fileBody).build();
    Request request = new Request.Builder().url(url).post(requestBody).build();

    execute(request);
}

/**
 * 上傳多個文件請求
 *
 * @param url       請求url
 * @param map       請求參數
 * @param filePaths 文件路徑
 * @return 返回結果。結果為""表示失敗
 */
private void uploadFiles(String url, Map map, List filePaths) {
    url = wrapUrl(url, map);

    MultipartBody.Builder builder = new MultipartBody.Builder();
    builder.setType(MultipartBody.FORM);
    for (String str : filePaths) {
        File file = new File(str);
        RequestBody fileBody = RequestBody.create(OCTET, file);
        builder.addFormDataPart("image", file.getName(), fileBody);
    }
    RequestBody requestBody = builder.build();
    Request request = new Request.Builder().url(url).post(requestBody).build();

    execute(request);
}

/**
 * 執行文件上傳操作
 *
 * @param request
 */
private void execute(Request request) {

    try {
        Response response = okHttpClient.newCall(request).execute();
        if (response.isSuccessful()) {
            callBack(response.body().string());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}


/**
 * 拼接get請求url
 *
 * @param url 請求url
 * @param map 參數
 * @return 返回拼接完的url地址
 */
private String wrapUrl(String url, Map map) {

    if (null == map) {
        return url;
    }

    url += "?";

    for (Map.Entry entry : map.entrySet()) {
        url += entry.getKey() + "=" + entry.getValue() + "&";
    }


    if (url.endsWith("&")) {
        url = url.substring(0, url.length() - 1);
    }
    return url;
}


/**
 * 請求客戶端
 */
private static OkHttpClient okHttpClient;


/**
 * Json媒體類型
 */
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

/**
 * 二進制流的媒體類型
 */
private static final MediaType OCTET = MediaType.parse("application/octet-stream");

}

public class RunThread {

private final String URL;

private HttpCommon httpCommon;

private int num;

private static ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100, 1000000L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());

private CountDownLatch countDownLatch;

/**
 * @param url 服務URL地址,
 * @param num 并發訪問次數,一般配置50+
 */
public RunThread(String url, int num) {



    this.URL = url;
    this.num = num;
    this.countDownLatch = new CountDownLatch(num);

    httpCommon = new HttpCommon() {
        @Override
        public void callBack(String responseString) {
            System.out.println(responseString);
        }
    };



}

public void testGet(Map map) {

    long startTime = System.currentTimeMillis();

    for (int i = 0; i < num; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                httpCommon.get(URL, map);
                countDownLatch.countDown();
            }
        });
    }

    try {
        countDownLatch.await();
        long executeTime = System.currentTimeMillis() - startTime;
        System.out.println("一共消耗:" + executeTime +"毫秒");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public  void testPost(Map map, T t) {

    long startTime = System.currentTimeMillis();

    for (int i = 0; i < num; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                httpCommon.post(URL, map, t);
                countDownLatch.countDown();
            }
        });
    }

    try {
        countDownLatch.wait();
        long executeTime = System.currentTimeMillis() - startTime;
        System.out.println("一共消耗:" + executeTime +"毫秒");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

public static void main(String[] args) {

    String Url = "http://localhost:8085/test/add";
    RunThread testMain = new RunThread(Url, 1000);

    // 測試Get請求
    testMain.testGet(new HashMap<>());

// // 測試POST請求、PUT請求、DELETE請求
// testMain.testPost(new HashMap<>(), null);

}

上面是并發測試代碼,那么如何寫高并發測試代碼呢!想到兩點:一個鎖、一個事務。先用Oracle做實驗。

insert into testa
  (aaaa, bbbb)
values
  (#{aaa}, #{aaa})


Service層代碼,設置事務的隔離級別為不可重復讀
Isolation.REPEATABLE_READ,結果報錯“Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: 僅 READ_COMMITTED 和 SERIALIZABLE 是有效的事務處理級”。臥槽!還能不能一起愉快地玩耍了,Oracle居然只支持可重復讀和可系列化兩種事務級別,真是讓人大跌眼鏡。

貼一下高并發代碼吧,經過實驗,通過1000個并發請求,使用Durid + Lock成功1百個不到(在這里還是得噴一下阿里的技術),使用dbcp2 + Lock成功2百多個,使用dbcp2 + synchronized 竟然成功了940個。
@Autowired
private TestMapper testMapper;

//private Lock lock = new ReentrantLock();

@Transactional(isolation = Isolation.SERIALIZABLE)
public synchronized Integer test(Integer a, Integer b) {

    int c = testMapper.select();
    c += 1;
    testMapper.insert(c);

    return c;

}

代碼有問題,找找錯誤原因吧。Spring AOP執行事務,會在Service方法執行之前就開始事務,再執行Synchronized同步方法。這樣會導致查詢數據并沒有做同步,修改成如下代碼,能完美解決問題。測試得出如下代碼的執行效率最高,1000個并發耗時9018毫秒
@Autowired
private TestMapper testMapper;

//private Lock lock = new ReentrantLock();

public synchronized Integer test(Integer a, Integer b) {

int c = testMapper.select();
c += 1;

update(c);

return c;

}

@Transactional(isolation = Isolation.SERIALIZABLE)
public void update(int c) {

testMapper.insert(c);

}

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71321.html

相關文章

  • 墻裂推薦:搜云庫技術團隊,面試必備的技術干貨

    摘要:今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...

    SegmentFault 評論0 收藏0
  • 墻裂推薦:搜云庫技術團隊,面試必備的技術干貨

    摘要:今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...

    Neilyo 評論0 收藏0
  • Node.js運行原理、并發性能測試對比生態圈匯總

    摘要:模式,單實例多進程,常用于多語言混編,比如等,不支持端口復用,需要自己做應用的端口分配和負載均衡的子進程業務代碼。就是我們需要一個調度者,保證所有后端服務器都將性能充分發揮,從而保持服務器集群的整體性能最優,這就是負載均衡。 showImg(https://segmentfault.com/img/remote/1460000019425391?w=1440&h=1080); Nod...

    kamushin233 評論0 收藏0
  • Node.js運行原理、并發性能測試對比生態圈匯總

    摘要:模式,單實例多進程,常用于多語言混編,比如等,不支持端口復用,需要自己做應用的端口分配和負載均衡的子進程業務代碼。就是我們需要一個調度者,保證所有后端服務器都將性能充分發揮,從而保持服務器集群的整體性能最優,這就是負載均衡。 showImg(https://segmentfault.com/img/remote/1460000019425391?w=1440&h=1080); Nod...

    BDEEFE 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<