在构建我分叉的Maven项目时,它运行src / test中的几个测试类,其中一个测试类特别麻烦:TestWriteAndRead
尝试运行此类时,测试永远不会完成。
package regalowl.simpledatalib.sql;
import static org.junit.Assert.*;
import org.junit.Test;
import regalowl.simpledatalib.SimpleDataLib;
import regalowl.simpledatalib.TestLogger;
import regalowl.simpledatalib.sql.Field;
import regalowl.simpledatalib.sql.FieldType;
import regalowl.simpledatalib.sql.SQLManager;
import regalowl.simpledatalib.sql.Table;
public class TestWriteAndRead {
@Test
public void testCreateShutdownAndLoad() {
SimpleDataLib sdl = new SimpleDataLib("test");
sdl.initialize();
sdl.setDebug(true);
new TestLogger(sdl);
SQLManager sm = sdl.getSQLManager();
sm.setWriteTaskInterval(1L);
sm.createDatabase();
SQLWrite sw = sm.getSQLWrite();
Table t = sm.addTable("hyperconomy_object_data");
Field f = t.addField("ID", FieldType.INTEGER);f.setPrimaryKey();f.setAutoIncrement();
f = t.addField("DATA", FieldType.TEXT);
sm.saveTables();
sw.writeSync(true);
String statement = "DELETE FROM hyperconomy_object_data";
sw.addToQueue(statement);
sw.writeSyncQueue();
sw.writeSync(false);
statement = "INSERT INTO hyperconomy_object_data (ID, DATA) VALUES ('" + 1 + "', ?)";
WriteStatement ws = new WriteStatement(statement, sdl);
ws.addParameter("test");
sw.addToQueue(ws);
sm.shutDown();
sdl.initialize();
sdl.setDebug(true);
new TestLogger(sdl);
sm = sdl.getSQLManager();
sm.createDatabase();
SQLRead sr = sm.getSQLRead();
QueryResult qr = sr.select("SELECT * FROM hyperconomy_object_data WHERE ID = '1'");
qr.next();
assertTrue(qr.getString("DATA").equals("test"));
}
}
不返回错误消息。测试开始,但从未结束
答案 0 :(得分:0)
我已经从https://github.com/RegalOwl/SimpleDataLib中签出了您正在使用的项目 似乎在SQLWrite类内部的私有类WriteTask的getActiveStatements方法中具有并发性boohoo。
该测试不稳定,并且卡在了第43行的shutdown调用上。一旦通过调试,我看到synchronized
在没有专用锁定对象的情况下使用,我立即怀疑并发问题。现在,研究这些我没有的类型的问题确实很耗时,但是我可以为您提供快速而又无意识的更改,以似乎可以解决该问题的原始代码:
private class WriteTask extends TimerTask {
ReentrantLock activeStatementsLock = new ReentrantLock();
//...keep the rest the same
public ArrayList<WriteStatement> getActiveStatements() {
synchronized (activeStatementsLock) {
return writeData;
}
}
}
在方法上使用synchronized
时,您基本上会执行与我的代码相同的操作,但是不是使用专用的activeStatementsLock
对象,而是使用执行此方法的实例对象(等效使用synchronized (this)
)。但是,当您有几种这样的方法时,很容易遇到各种麻烦,例如死锁和诸如此类的问题,因此您可以通过拥有几个专用的锁定对象来对这些同步块进行分组。
在这种情况下,活动语句似乎与其他两个语句无关,并且将它们拆分可能是安全的,但是我不能保证。
请注意,我不知道问题的根本原因,因此我不确定此代码如何解决问题(或者我没有时间深入探讨此问题),并且更好的解决方案,您应该将此作为Bug提交给https://github.com/RegalOwl/SimpleDataLib/issues上的github问题,在那里,专门的贡献者将很乐意在自己的项目中解决问题。