这个问题仍然存在this问题。
我正在尝试停止将行插入dabase的线程,但我总是遇到异常
这部分代码显示了我的线程的逻辑
public void run() {
String number = "";
try {
while (!Thread.currentThread().isInterrupted()) {
number = generateNumber();
database.insertOrUpdateRow(number);
}
} catch (SQLException ex) {
LOGGER.error("exception while inserting number " + number + " " + ex.getMessage());
}
}
我已经搜索了如何正确停止线程,并发现我应该标记该线程已停止。 所以,这就是我得到的
public boolean stop() {
try {
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread t : threadSet) {
if (t != null) {
if (t.getName().contains("generate")) {
t.interrupt();
LOGGER.info(t.getName()+" is stopped");
}
}
}
} catch (Exception e) {
LOGGER.error("Exception when call stop: " + e.toString());
}
return true;
}
我的堆栈跟踪
[INFO] [qtp1804418913-32] INFO se.homework.hwbs.tasks.un.server.NumberQtyService
Impl - generate37 is stopped
[INFO] [generate37] ERROR se.homework.hwbs.tasks.un.server.threads.InsertRowThre
ad - exception while inserting number 34587 transaction rollback: serialization
failure
[INFO] [qtp1804418913-33] ERROR se.homework.hwbs.tasks.un.server.database.Databa
se - error select cnt by numberjava.sql.SQLTransactionRollbackException: transac
tion rollback: serialization failure
[INFO] [qtp1804418913-34] ERROR se.homework.hwbs.tasks.un.server.database.Databa
se - error select cnt by numberjava.sql.SQLTransactionRollbackException: transac
tion rollback: serialization failure
线程停止,一切正常,但这种例外让我感觉很糟糕。他们为什么会这样?当我以正确的方式使用数据库时如何停止线程? 数据库是HsqlDB。
答案 0 :(得分:1)
您可以考虑在插入线程中使用可以直接控制的停止变量,而不是枚举线程并按名称选择一个。
考虑一下这个GeneratorThread:
public class GeneratorThread extends Thread {
protected static volatile boolean stop;
public static void stopExecution() {
stop = true;
}
public GeneratorThread() {
stop = false;
}
public void run() {
String number = "";
try {
while (!stop) {
number = generateNumber();
database.insertOrUpdateRow(number);
}
} catch (SQLException ex) {
//Any SQLException will terminate your thread. Is this wanted?!
LOGGER.error("exception while inserting number " + number + " " + ex.getMessage());
}
}
}
你可以通过调用GeneratorThread.stopExecution()
来阻止这种情况,GeneratorThread
将标志设置为false,导致当前号码成为最后插入的数字。
因为这意味着您的应用程序中只会有一个 while (!stop) {
String number = "";
try {
number = generateNumber();
database.insertOrUpdateRow(number);
} catch (SQLException ex) {
LOGGER.error("exception while inserting number " + number + " " + ex.getMessage());
}
}
。
同样,你可能会重新考虑你的同时和尝试捕捉位置。该线程将以任何SQLException结束。如果你想保持线程运行,即使有(临时?)错误,你可能想要
{{1}}
答案 1 :(得分:0)
我结合了@Jan和@Fildor的想法。
所以,这就是我得到的
public class GeneratingThread extends Thread {
private final Logger LOGGER = LoggerFactory.getLogger(InsertRowThread.class);
private final Database database;
private boolean stop = false;
public GeneratingThread(Database database) {
this.database = database;
}
@Override
public void run() {
String number = "";
try {
while (!stop) {
number = generateNumber();
database.insertOrUpdateRow(number);
}
} catch (SQLException ex) {
LOGGER.error("exception while inserting number " + number + " " + ex.getMessage());
}
}
public void stopThread() {
this.stop = true;
}
private String generateNumber() {
int number = ThreadLocalRandom.current().nextInt(0, 100000);
String sb = Integer.toString(number);
while (sb.length() < 5) {
sb = "0" + sb;
}
return sb;
}
}
这是我开始的话题
private final List<GeneratingThread> generatingThreads = new ArrayList<>();
GeneratingThread thread = new GeneratingThread(db);
thread.start();
generatingThreads.add(thread);
然后停止
for (GeneratingThread gt : generatingThreads) {
if (gt != null) {
gt.stopThread();
LOGGER.info("Thread is stopped");
}
}
对我来说很完美。谢谢你的讨论!