Thread join方法结合实战
程序员文章站
2022-05-04 10:10:04
...
该例子是典型的串行任务局部并行化处理,用户在App客户端输入出发地“北京”和目的地上海,服务器接收到这个请求之后, 先来验证用户的信息,然后到各大航空公司的接口查询信息,最后经过整理加工返回给客户端,每一个航空公司的接口不会都一样, 获取的数据格式也不一样,查询的速度也存在这差异,如果再跟航空公司进行串行化交互(逐个的查询),很明显客户端需要等待很长的时间。 这样的话,用户的体验很差。我们将每一个航空公司的查询都交给一个线程去做,然后再他们结束工作之后统一对数据进行整理, 这样就可以极大的节约时间,从而提高用户体验效果。
说明:本次只是单纯用Thread的api来实现这种效果,当然JDK也自带了很多高级工具,比如CountDownLatch和CyclicBarrier都可以完成类似的功能,在此不详细展开。
import java.util.List;
public interface FightQuery {
List<String> get();
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
public class FightQueryTask extends Thread implements FightQuery{
private final String origin;
private final String destination;
private final List<String> flightList=new ArrayList<>();
public FightQueryTask(String airLine, String origin, String destination){
super("["+airLine+"]");//Thread的名字构造方法
this.origin=origin;
this.destination=destination;
}
@Override
public List<String> get() {
return this.flightList;
}
@Override
public void run() {
System.out.printf("%s-query from %s to %s \n",getName(),origin,destination);
int randomVal = ThreadLocalRandom.current().nextInt(10);
try {
TimeUnit.SECONDS.sleep(randomVal);
this.flightList.add(getName()+"-"+randomVal);
System.out.printf("The Flight:%s list query successful\n",getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class FlightQueryExample {
//合作的各大航空公司
private static List<String> fightCompany = Arrays.asList("CSA", "CEA", "HNA");
public static void main(String[] args) {
List<String> result = search("SH", "BJ");
System.out.println("=========result==========");
result.forEach(System.out::println);
}
private static List<String> search(String origin,String dest){
final List<String> result=new ArrayList<>();
//创建查询航班信息的线程列表
List<FightQueryTask> fightQueryTaskList = fightCompany.stream().map(f -> createSearchTask(f, origin, dest)).collect(Collectors.toList());
//分别启动这几个线程
fightQueryTaskList.forEach(Thread::start);
//分别调用每一个线程的join方法,阻塞当前线程
fightQueryTaskList.forEach(fightQueryTask -> {
try {
fightQueryTask.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
//在此之前,当前线程会阻塞住,获取每一个查询线程的结果,并且加入到result中
fightQueryTaskList.stream().map(FightQueryTask::get).forEach(result::addAll);
return result;
}
private static FightQueryTask createSearchTask(String flight,String ori,String dest){
return new FightQueryTask(flight,ori,dest);
}
}
运行结果: