开发过程中经常遇到如下需求,拿到一个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;
}
@Override
public 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;
}
@Override
public void run() {
try {
sendRequest(user);
} catch (Exception e) {
} finally {
countDownLatch.countDown();
}
}
}
}
@Data
class User {
private String idCard;
private String name;
}
|