1 基本使用
要求
1 大量线程希望分批次执行,批次间同步,批次可以异步执行
2 系统有最大线程数限制,不可以同时创建大量线程
public static void main(String[] args) throws InterruptedException {
int jobs = 11, MAX_THREAD_NUMBER = 3, BATCH_NUMBER = 5;
Semaphore semaphore = new Semaphore(MAX_THREAD_NUMBER);
int loops = jobs / BATCH_NUMBER + jobs % BATCH_NUMBER;
for (int i = 0; i < loops; i++) {
int left_job = Math.min(BATCH_NUMBER, jobs - i * BATCH_NUMBER);
CountDownLatch countDownLatch = new CountDownLatch(left_job);
System.err.printf("第 %d 批数据开始执行,总共 %d 个数据\n", i + 1, left_job);
for (int j = 0; j < left_job; j++) {
int finalI = i, finalJ = j;
new Thread(() -> {
try {
semaphore.acquire();
Thread.sleep(new Random().nextInt(200));
System.err.printf("第 %d 批第 %d 个数据执行完毕\n", finalI + 1, finalJ + 1);
semaphore.release();
countDownLatch.countDown();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
countDownLatch.await();
System.err.printf("第 %d 批数据执行完毕,这里统一处理这批数据...\n", i + 1);
Thread.sleep(new Random().nextInt(1000));
}
}
执行结果
第 1 批数据开始执行,总共 5 个数据
第 1 批第 1 个数据执行完毕
第 1 批第 4 个数据执行完毕
第 1 批第 2 个数据执行完毕
第 1 批第 3 个数据执行完毕
第 1 批第 5 个数据执行完毕
第 1 批数据执行完毕,这里统一处理这批数据...
第 2 批数据开始执行,总共 5 个数据
第 2 批第 1 个数据执行完毕
第 2 批第 2 个数据执行完毕
第 2 批第 5 个数据执行完毕
第 2 批第 3 个数据执行完毕
第 2 批第 4 个数据执行完毕
第 2 批数据执行完毕,这里统一处理这批数据...
第 3 批数据开始执行,总共 1 个数据
第 3 批第 1 个数据执行完毕
第 3 批数据执行完毕,这里统一处理这批数据...
2 优化写excel
public class ExcelUtils {
public static final int SHEET_MAX_ROWS = 20_0000;
public static <T> Workbook write(List<T> list, String[] header) throws InterruptedException {
Workbook workbook = new XSSFWorkbook();
int sheets = (int) Math.ceil(list.size() / (SHEET_MAX_ROWS + 0.0));
Semaphore semaphore = new Semaphore(5);
CountDownLatch countDownLatch = new CountDownLatch(sheets);
for (int i = 0; i < sheets; i++) {
Sheet sheet = workbook.createSheet();
int finalI = i;
new Thread(() -> {
try {
semaphore.acquire();
doWrite(list, finalI, sheet, header);
} catch (IllegalAccessException | InterruptedException e) {
throw new RuntimeException(e);
} finally {
semaphore.release();
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
return workbook;
}
private static <T> void doWrite(List<T> list, int from, Sheet sheet, String[] header) throws IllegalAccessException {
int start = from * SHEET_MAX_ROWS;
int end = Math.min(SHEET_MAX_ROWS, list.size() - start);
doWriteHeader(sheet.createRow(0), header);
for (int i = start; i < start + end; i++) {
Row row = sheet.createRow(i + 1 - start);
T t = list.get(i);
doWriteValue(t, row);
}
}
private static void doWriteHeader(Row row, String[] header) {
for (int i = 0; i < header.length; i++) {
row.createCell(i, CellType.STRING).setCellValue(header[i]);
}
}
private static <T> void doWriteValue(T t, Row row) throws IllegalAccessException {
Field[] fields = t.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (field.getName().equals("HEADER")) continue;
field.setAccessible(true);
Object o = field.get(t);
if (o instanceof String) {
row.createCell(i, CellType.STRING).setCellValue((String) o);
} else if (o instanceof Integer) {
row.createCell(i, CellType.NUMERIC).setCellValue((int) o);
} else if (o instanceof Boolean) {
row.createCell(i, CellType.BOOLEAN).setCellValue((Boolean) o);
} else {
row.createCell(i, CellType.BLANK).setCellValue(String.valueOf(o));
}
}
}
}