java实现使用线程池多线程分页插入数据
时间: 2023-11-14 20:25:13 浏览: 106
好的,这个问题我可以帮你回答。以下是 Java 实现使用线程池多线程分页插入数据的代码示例:
```java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MultiThreadInsert {
private static final int BATCH_SIZE = 500;
private static final int THREAD_POOL_SIZE = 10;
public void insert(List<Data> dataList) {
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
int totalSize = dataList.size();
int totalPages = (int) Math.ceil((double) totalSize / BATCH_SIZE);
for (int i = 0; i < totalPages; i++) {
int startIndex = i * BATCH_SIZE;
int endIndex = Math.min((i + 1) * BATCH_SIZE, totalSize);
List<Data> subList = dataList.subList(startIndex, endIndex);
executorService.execute(new InsertTask(subList));
}
executorService.shutdown();
}
private static class InsertTask implements Runnable {
private List<Data> dataList;
public InsertTask(List<Data> dataList) {
this.dataList = dataList;
}
@Override
public void run() {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = getConnection(); // 获取数据库连接
connection.setAutoCommit(false); // 关闭自动提交
String sql = "INSERT INTO table_name (column1, column2, ...) VALUES (?, ?, ...)";
preparedStatement = connection.prepareStatement(sql);
for (Data data : dataList) {
preparedStatement.setString(1, data.getColumn1());
preparedStatement.setInt(2, data.getColumn2());
// 继续设置 preparedStatement 的参数
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
connection.commit(); // 提交事务
} catch (SQLException e) {
// 处理异常
} finally {
close(preparedStatement);
close(connection);
}
}
private Connection getConnection() throws SQLException {
// 获取数据库连接
}
private void close(Connection connection) {
// 关闭数据库连接
}
private void close(PreparedStatement preparedStatement) {
// 关闭 PreparedStatement
}
}
private static class Data {
private String column1;
private int column2;
// 其他属性及 setter、getter 方法
}
}
```
其中,`MultiThreadInsert` 类中的 `insert` 方法接收一个 `List<Data>` 参数,表示需要插入的数据列表。该方法将数据按照 BATCH_SIZE(每批次插入的数据量) 进行分页,然后使用固定大小的线程池(大小为 THREAD_POOL_SIZE)执行插入操作。
`InsertTask` 类表示每个插入任务,其中的 `run` 方法会在新的线程中执行。在 `run` 方法中,首先获取数据库连接并关闭自动提交,然后根据每个数据对象设置 `PreparedStatement` 的参数,并将插入语句添加到批处理中,最后执行批处理并提交事务。如果执行过程中发生异常,需要进行异常处理并关闭数据库连接和 `PreparedStatement`。
需要注意的是,在插入操作中应该尽量避免使用锁,因为锁会降低多线程并发执行的效率。另外,数据的插入顺序可能会被打乱,所以如果需要保证数据的顺序,需要在查询时进行排序。
阅读全文