作者:梦魇心芽_932 | 来源:互联网 | 2023-06-08 15:38
开发过程中经常遇到如下需求,拿到一个list
数据,需要遍历它然后请求第三方接口,然后根据返回结果做一些事
常规写法
public static void main(String[] args) {List<User> list = getList();test1(list);
}
static List<User> getList() {List<User> list = new ArrayList<>();for (int i = 1; i < 501; i++) {User user = new User();user.setIdCard(i + "");list.add(user);}return list;
}
static void test1(List<User> list) {long start = System.currentTimeMillis();for (User user : list) {sendRequest(user);}long end = System.currentTimeMillis();System.out.println("单线程方法,耗时:" + (end - start) + "ms");
}
static void sendRequest(User user){try {Thread.sleep(10);} catch (Exception e){}user.setName("张三-" + user.getIdCard());System.out.println("=====> 发送请求: name=" + user.getName());
}@Data
class User {private String idCard;private String name;
}
我们使用模拟数据造了 500 条数据,然后for
循环列表去请求第三方接口获取数据,总共耗时大约为10 * 500 = 5000ms
以上
使用多线程改造后:
public static void main(String[] args) {List<User> list = getList();test2(list);
}
static void test2(List<User> list) {long start = System.currentTimeMillis();ExecutorService executor = Executors.newFixedThreadPool(10);final CountDownLatch countDownLatch = new CountDownLatch(list.size());for (User user : list) {executor.execute(new Task(user, countDownLatch));}try {countDownLatch.await();} catch (Exception e) {} finally {executor.shutdown();}long end = System.currentTimeMillis();System.out.println("多线程方法,耗时:" + (end - start) + "ms");
}
static class Task implements Runnable {private User user;private CountDownLatch countDownLatch;public Task(User user, CountDownLatch countDownLatch) {this.user = user;this.countDownLatch = countDownLatch;}@Overridepublic void run() {try {sendRequest(user);} catch (Exception e) {} finally {countDownLatch.countDown();}}}
结果:
注意事项:
- 正常情况下,我们需要等多线程处理完,获取
list
数据,再去做一些业务操作(如入库,导出数据等),如果不需要等待结果,可以去掉countDownLatch
,速度会更快 Task
的run
方法最好使用try...catch...finally
,保证无论sendRequest()
方法执行成功与否,countDownLatch
都能减1,防止多线程无法终止
完整Demo
public class ForThreadTest {public static void main(String[] args) {List<User> list = getList();test1(list);test2(list);}static void test1(List<User> list) {long start = System.currentTimeMillis();for (User user : list) {sendRequest(user);}long end = System.currentTimeMillis();System.out.println("单线程方法,耗时:" + (end - start) + "ms");}static void test2(List<User> list) {long start = System.currentTimeMillis();ExecutorService executor = Executors.newFixedThreadPool(10);final CountDownLatch countDownLatch = new CountDownLatch(list.size());for (User user : list) {executor.execute(new Task(user, countDownLatch));}try {countDownLatch.await();} catch (Exception e) {} finally {executor.shutdown();}long end = System.currentTimeMillis();System.out.println("多线程方法,耗时:" + (end - start) + "ms");}static List<User> getList() {List<User> list = new ArrayList<>();for (int i = 1; i < 501; i++) {User user = new User();user.setIdCard(i + "");list.add(user);}return list;}static void sendRequest(User user){try {Thread.sleep(10);} catch (Exception e){}user.setName("张三-" + user.getIdCard());System.out.println("=====> 发送请求: name=" + user.getName());}static class Task implements Runnable {private User user;private CountDownLatch countDownLatch;public Task(User user, CountDownLatch countDownLatch) {this.user = user;this.countDownLatch = countDownLatch;}@Overridepublic void run() {try {sendRequest(user);} catch (Exception e) {} finally {countDownLatch.countDown();}}}
}@Data
class User {private String idCard;private String name;
}