1. 程式人生 > 實用技巧 >多執行緒 實現高效多借口呼叫

多執行緒 實現高效多借口呼叫

正常情況下我們呼叫多借口,都會順序呼叫,也就是序列,如果藉口直接沒有任何關係,而序列執行消耗的時間,就是各個藉口直接呼叫的總和。而jdk其實給我們提供有返回值型別執行緒,可以解決這個問題。

測試基類:用於統計執行時間

import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;

import com.ms.cloud.common.util.frame.SpObserver;

@RunWith(SpringRunner.
class) public class BaseTest { private Long starttime; @Rule public TestName junitClass= new TestName(); @Before public void before() { starttime = System.currentTimeMillis(); setDataSource(); System.out.println(junitClass.getMethodName() + "....................start....................
"); } @After public void after() { double usedtime = (System.currentTimeMillis() - starttime) / 1000.0; System.out.println("耗時 " + usedtime + " ms"); System.out.println(junitClass.getMethodName() + "....................end...................."); } protected void
setDataSource() { this.setDataSource(null, null); } protected void setDataSource(String city, String sourceType) { if (StringUtils.isEmpty(city)) { city = "sz"; } if (StringUtils.isEmpty(sourceType)) { sourceType = "PC"; } SpObserver.putSoruce(sourceType); SpObserver.putSp(city); } }

工具類,模擬使用者呼叫多借口。每個介面消耗幾秒鐘。。

import java.util.concurrent.TimeUnit;

public class UserUtils {

    public static String getHead(String uid) throws InterruptedException {
        TimeUnit.SECONDS.sleep(2);
        return ""+uid+"】的頭";
    }
    public static String getFace(String uid)throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        return ""+uid+"】的臉";
    }
    public static String getFoot(String uid) throws InterruptedException {
        TimeUnit.SECONDS.sleep(7);
        return ""+uid+"】的腳";
    }
}

正常情況下我們執行程式如此:

普通人:

import org.junit.Test;

public class MyGodTest extends BaseTest {

    @Test
    public void testDo() throws InterruptedException {
        String uid = "路人甲";
        StringBuffer sb = new StringBuffer();
        sb.append(UserUtils.getHead(uid)).append("\n");
        sb.append(UserUtils.getFace(uid)).append("\n");
        sb.append(UserUtils.getFoot(uid)).append("\n");
        System.out.println("資訊為:\n" + sb.toString());
    }
}

直接串聯:執行結果耗時14+s

testDo....................start....................
資訊為:
【路人甲】的頭
【路人甲】的臉
【路人甲】的腳

耗時 14.016 ms testDo....................end....................

老程式設計師:

開啟多執行緒,非同步模式。用執行緒池與不用都可以。。讓執行緒跑起來就行

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import org.junit.Test;

/**
 * @desc 採用執行緒方式 
 * @author 陳惟鮮 chenweixian
 * @date 2020年7月23日 下午1:00:23
 *
 */
public class MyGodThreadTest extends BaseTest {

    /**用執行緒執行
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @Test
    public void testDo() throws InterruptedException, ExecutionException {
        String uid = "路人甲";
        StringBuffer sb = new StringBuffer();
        Callable<String> headCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getHead(uid);
            }
        };
        
        Callable<String> faceCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFace(uid);
            }
        };
        
        Callable<String> footCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFoot(uid);
            }
        };
        // 
        FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
        FutureTask<String> faceFutureTask = new FutureTask<>(faceCallable);
        FutureTask<String> footFutureTask = new FutureTask<>(footCallable);
        
        // 執行方法,執行緒非同步執行
        new Thread(headFutureTask).start();
        new Thread(faceFutureTask).start();
        new Thread(footFutureTask).start();
        
        sb.append(headFutureTask.get()).append("\n");
        sb.append(faceFutureTask.get()).append("\n");
        sb.append(footFutureTask.get()).append("\n");
        System.out.println("資訊為:\n" + sb.toString());
    }
    
    /**用執行緒池執行
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @Test
    public void testPoolDo() throws InterruptedException, ExecutionException {
        String uid = "路人甲";
        StringBuffer sb = new StringBuffer();
        Callable<String> headCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getHead(uid);
            }
        };
        
        Callable<String> faceCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFace(uid);
            }
        };
        
        Callable<String> footCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFoot(uid);
            }
        };
        // 
        FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
        FutureTask<String> faceFutureTask = new FutureTask<>(faceCallable);
        FutureTask<String> footFutureTask = new FutureTask<>(footCallable);
        
        // 執行方法,執行緒非同步執行
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(headFutureTask);
        executor.submit(faceFutureTask);
        executor.submit(footFutureTask);
        executor.shutdown();
        
        sb.append(headFutureTask.get()).append("\n");
        sb.append(faceFutureTask.get()).append("\n");
        sb.append(footFutureTask.get()).append("\n");
        System.out.println("執行緒池資訊為:\n" + sb.toString());
    }
}

執行結果:7+s

testPoolDo....................start....................
執行緒池資訊為:
【路人甲】的頭
【路人甲】的臉
【路人甲】的腳

耗時  7.02 ms
testPoolDo....................end....................

總結:

多學多看,多實踐,對工作有幫助。

核心部分如下

Callable<String> footCallable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return UserUtils.getFoot(uid); == 業務處理
            }
        };
FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
new Thread(faceFutureTask).start(); ==執行程式
footFutureTask.get() ==得到響應結果