- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对多线程编码完全陌生。
这是我的要求:我有一个包含 50 000 - 300 000 条记录的文件。
它是基于列的数据(4 列),以空格作为分隔符。我需要使用空格分割行并将记录保存在 DB 中的 4 列中。
我想开发一个多线程应用程序,它将数据插入到具有 4 列的 H2 DB(使用 JDBC/其他什么?),大约需要 2 秒。我需要根据收到的记录数动态更改线程池大小。
我正在使用 Java Swings 开发桌面应用程序。 (不是基于网络的应用程序)
我不知道是否有更好的并发类可以更快地完成此任务。
如果不是多线程,还有其他办法吗?或任何其他框架?
添加批处理后,大约需要 5 秒,处理 250,000 条记录:
BufferedReader in = new BufferedReader(new FileReader(file));
java.util.List<String[]> allLines = new ArrayList<String[]>(); // used for something else
String sql = "insert into test (a, b, c, d)” +
" values (?,?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
int i=0;
while ((line = in.readLine()) != null) {
line = line.trim().replaceAll(" +", " ");
String[] sp = line.split(" ");
String msg = line.substring(line.indexOf(sp[5]));
allLines.add(new String[]{sp[0] + " " + sp[1], sp[4], sp[5], msg});
pstmt.setString(1, sp[0] + " " + sp[1]);
pstmt.setString(2, sp[4]);
pstmt.setString(3, sp[5]);
pstmt.setString(4, msg);
pstmt.addBatch();
i++;
if (i % 1000 == 0){
pstmt.executeBatch();
conn.commit();
}
}
pstmt.executeBatch();
最佳答案
通过以下方式改进逻辑:
PreparedStatement
的实例上创建并在每次插入时使用它这可以通过以下方式完成:
private PreparedStatement pstmt;
public BatchInsertion(String sql) throws SQLException{
pstmt = conn.prepareStatement(sql)
}
public int insert(String a, String b, String c, String d) throws SQLException{
pstmt.setString(1, a);
pstmt.setString(2, b);
pstmt.setString(3, c);
pstmt.setString(4, d);
pstmt.addBatch();
return batchSize++;
}
public void sendBatch() throws SQLException{
pstmt.executeBatch();
}
在那里,您只需要管理该实例的插入,当您到达最后一个项目或说批处理中的 1000 个项目时,发送它。
我用它来不强制插入 Collection
首先。
注意:最后需要关闭语句,我会实现AutoCloseable
在这样的类上执行此操作,并且您需要尝试使用资源才能安全。
如果您需要多线程此插入。我建议采用以下架构:
创建一个线程池,每个线程池都会有一个连接和一批插入数据。使用一个队列来插入从文件中推送数据。每个线程都会获取一个值并将其添加到批处理中。
通过这种架构,您可以轻松增加线程数量。
一、轻量化BatchInsert
类能够使其运行:
class BatchInsert implements AutoCloseable {
private int batchSize = 0;
private final int batchLimit;
public BatchInsert(int batchLimit) {
this.batchLimit = batchLimit;
}
public void insert(String a, String b, String c, String d) {
if (++batchSize >= batchLimit) {
sendBatch();
}
}
public void sendBatch() {
System.out.format("Send batch with %d records%n", batchSize);
batchSize = 0;
}
@Override
public void close() {
if (batchSize != 0) {
sendBatch();
}
}
}
然后,我使用某种平衡器来提供一个队列和一些 Thread
共享同一个队列。
class BalanceBatch {
private final List<RunnableBatch> threads = new ArrayList<>();
private Queue<String> queue = new ConcurrentLinkedQueue<>();
private static final int BATCH_SIZE = 50_000;
public BalanceBatch(int nbThread) {
IntStream.range(0, nbThread).mapToObj(i -> new RunnableBatch(BATCH_SIZE, queue)).forEach(threads::add);
}
public void send(String value) {
queue.add(value);
}
public void startAll() {
for (RunnableBatch t : threads) {
new Thread(t).start();
}
}
public void stopAll() {
for (RunnableBatch t : threads) {
t.stop();
}
}
}
然后我实现读取这些可运行实例的队列的逻辑。他们的想法是读取队列并将其发送到批处理,直到队列为空并收到命令“STOP”。
class RunnableBatch implements Runnable {
private boolean started = true;
private Queue<String> queue;
private int batchLimit;
public RunnableBatch(int batchLimit, Queue<String> queue) {
this.batchLimit = batchLimit;
this.queue = queue;
}
@Override
public void run() {
try (BatchInsert batch = new BatchInsert(batchLimit)) {
while (!queue.isEmpty() || started) {
String s = queue.poll();
if (s == null) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
} else {
String[] values = s.split(";");
batch.insert(values[0], values[1], values[2], values[3]);
}
}
}
}
public void stop() {
started = false;
}
}
我通过基本测试尝试了这个
public static void main(String[] args) throws IOException {
createDummy("/tmp/data.txt", 25_000_000);
BalanceBatch balance = new BalanceBatch(10);
balance.startAll();
try (Stream<String> stream = Files.lines(Paths.get("/tmp/data.txt"))) {
stream.forEach(balance::send);
} catch (Exception e1) {
e1.printStackTrace();
}
balance.stopAll();
}
public static void createDummy(String file, int nbLine) throws IOException {
Files.write(Paths.get(file), (Iterable<String>) IntStream.range(0, nbLine).mapToObj(i -> String.format("A%d;B%d;C%d;D%d", i, i, i, i))::iterator);
}
这将打印发送的每一批,并显示最后一批将是相当随机的,因为余额不是“恒定的”。示例:10 个线程,每批 50k 条记录:
Send batch with 50000 records
...
Send batch with 50000 records
Send batch with 15830 records
Send batch with 15844 records
Send batch with 2354 records
Send batch with 14654 records
Send batch with 40181 records
Send batch with 44994 records
Send batch with 38376 records
Send batch with 17187 records
Send batch with 27047 records
Send batch with 33533 records
警告:createDummy
函数将创建一个包含 25_000_000 行的文件(我已对其进行了评论)。这大约是一个 1GB 数据的文件
我需要更多时间来做一些基准测试,目前我没有任何用于大规模插入的数据库。
<小时/>混合使用这个多线程文件读取器和批处理应该会给你带来好的结果。
请注意,这可能不是多线程的最佳实现,我从来没有研究过这个主题。我愿意接受建议/改进。
关于java - 处理文件和数据库插入的最快方法 - Java 多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49811474/
什么是更快的安卓? Color.rgb(184, 134, 011); 或 Color.parseColor("#234181"); 还是别的什么? 答案:最快的似乎是: int mycolor =
没错, 基本上我需要计算出从服务器到最终用户的最短路线。我有 2 台服务器 - 一台在英国,一台在美国。 我需要根据最终用户的位置确定从哪个服务器加载内容。 我最初想使用 fsock/curl/fgc
我正在阅读固定宽度整数类型 ( cpp reference) 并遇到int_fast8_t、int_fast16_t、int_fast32_t 和 int_least8_t 类型,int_least1
Closed. This question is opinion-based。它当前不接受答案。 想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。 6年前关闭。
我有大量目录,我想尽快读取所有文件。我的意思是,不是 DirectoryInfo.GetFiles 快,而是“get-clusters-from-disk-low-level”快。 当然,.NET 2
我尝试寻找最小的可被1到n整除的数字,现在我正在寻求有关进一步压缩/使我的解决方案更有效的方法的建议。如果也有O(1)解决方案,那将非常酷。 def get_smallest_number(n):
有很多不同的方法可以在驱动程序之间选择元素。我想知道哪一个最快且最适合 native 应用程序(iOS 和 Android)。 Appium Driver 类有: findElementByAcces
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
让矩阵 A 说 A = magic(100);。我见过两种计算矩阵 A 的所有元素之和的方法。 sumOfA = sum(sum(A)); 或者 sumOfA = sum(A(:)); 其中一个比另一
我想为玩具车在没有障碍物的平面 (2d) 上规划一条路线。玩具车应该从点 (p1x,p1y) 移动到 (p2x,p2y)(又名狄利克雷边界条件)。此外,玩具车在起点的速度是(v1x,v1y),终点处要
假设有 n 个 3 维对象(多面体)。最快的方法是计算所有对象的交集O(n^2)? 现在,我正在使用一个基本上强制 T(n) 等于 n ^ 2 的库: for each object: // ther
关闭。这个问题需要 details or clarity 。它目前不接受答案。 想改进这个问题吗? 添加细节并通过 editing this post 澄清问题。 关闭 5 年前。 Improve
在 c: 上,我有数以万计的 *.foobar 文件。它们在各种各样的地方(即子目录)。这些文件的大小大约为 1 - 64 kb,并且是纯文本。 我有一个 class Foobar(string fi
我的基本问题是有多个线程做一些事情,其中一些需要比其他线程更多的时间(20 倍甚至更多),他们需要的时间只取决于起始值,但不能从起始值预测单独他们需要多少时间。为了减少更快线程的空闲时间,我想通过
好的,我有一个疑问: select distinct(a) from mytable where b in (0,3) 什么会更快,上面的还是 select distinct(a) from myta
问题简介: 我正在开发一个生态生理模型,我使用了一个名为 S 的引用类列表。存储模型需要输入/输出的每个对象(例如气象、生理参数等)。 此列表包含 5 个对象(请参见下面的示例): - 两个数据帧,S
我有一个正在工作的问题陈述,但我仍然想知道更高效、更快,更重要的是正确设计来处理下面提到的场景。 我有一个 POJO 类 class A { String s; Double d; } 我正在
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 3 年前。 Improve this q
关于 LLVM 如何优化代码,关于 SO 以及整个网络都有一些非常好的描述。但这些都无法回答我的具体问题。 在 Xcode 中,项目和目标设置中有各种代码优化选项。我理解在开发过程中不需要优化,但为什
我正在用 C# 开发一个服务器项目,在收到 TCP 消息后,它会被解析并存储在一个精确大小的 byte[] 中。 (不是固定长度的缓冲区,而是存储所有数据的绝对长度的字节[]。) 现在为了阅读这个 b
我是一名优秀的程序员,十分优秀!