正常情况下我们调用多借口,都会顺序调用,也就是串行,如果借口直接没有任何关系,而串行执行消耗的时间,就是各个借口直接调用的总和。而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(" "); sb.append(UserUtils.getFace(uid)).append(" "); sb.append(UserUtils.getFoot(uid)).append(" "); System.out.println("信息为: " + 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(" "); sb.append(faceFutureTask.get()).append(" "); sb.append(footFutureTask.get()).append(" "); System.out.println("信息为: " + 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(" "); sb.append(faceFutureTask.get()).append(" "); sb.append(footFutureTask.get()).append(" "); System.out.println("线程池信息为: " + 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() ==得到响应结果