我有一个非常讨厌的问题,我自己无法解决这个问题。
我有一个简单的JavaFX场景,只有2个按钮用于启动和终止线程。在这种情况下,停止操作无关紧要,因为我无法使线程正常工作。 actionListener看起来像:
EDIT1:找出问题,不特定于线程,这是针对TimeServer的请求,请看这里:answer
感谢大家回答此问题或阅读问题! :)
private FarmAction action = null;
@FXML
void btnStartListener(ActionEvent event) {
Firefox ff = new Firefox();
ff.startBrowser();
BrowserAction browserAction = new BrowserAction(ff.getDriver(), ff.getJse());
browserAction.loginToGame(user, pass);
ObservableList<AttackCommand> list = (ObservableList<AttackCommand>) Serializer.deserialize(Constants.FILE_NAME_TESTPURPOSE);
if(action == null)
action = new FarmAction(ff.getDriver(), ff.getJse(), list);
Thread run = new Thread(action);
try {
run.start();
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable t) {
t.printStackTrace();
}
}
注意:我正在使用Selenium Framework来自动化一些点击 网站。
我的FarmAction类看起来像这样:
public class FarmAction implements Runnable{
private WebDriver driver;
private JavascriptExecutor jse;
private ObservableList<AttackCommand> attackList;
private boolean stop = false;
public FarmAction(WebDriver driver, JavascriptExecutor jse, ObservableList<AttackCommand> attackList) {
this.driver = driver;
this.jse = jse;
for(AttackCommand ac : attackList)
{
ac.transferFromPropToAttributes();
}
this.attackList = attackList;
}
@Override
public void run() {
ArrayList<Integer> unitIds = Constants.UNIT_ID_LIST_ALL;
if(!driver.getCurrentUrl().equals(Constants.URL_TESTPURPOSE))
driver.navigate().to(Constants.URL_TESTPURPOSE);
int count = 0;
while(true) { // Just let the Thread run for duration = lifetime of application
System.out.println(count++); //count how often the thread runs into this while loop before terminating for no reason
for(AttackCommand ac : attackList) {
for(int i = 0; i < unitIds.size(); i ++) {
int unitKey = unitIds.get(i); // Momentane UnitID der Iteration
if(ac.getUnits().containsKey(unitKey) && ( ac.getTurnBackTime() == 0 ||ac.getTurnBackTime() <= DateUtil.getActualServerTime())) // getActualServerTime is request against the timeserver de.pool.ntp.org
{
String textfieldName = Constants.HASHMAP_TEXTFIELD_NAME_ALL_HTML_PLACE.get(unitKey);
WebElement textfield = driver.findElement(By.name(textfieldName));
textfield.sendKeys(String.valueOf(ac.getUnits().get(unitKey)));
WebElement textfieldCoordinates = driver.findElement(By.name(Constants.TEXTFIELD_NAME_HTML_PLACE_COODRINATESFORTARGET));
textfieldCoordinates.sendKeys(StringHelper.getPointAsString(new Point(ac.getXCoordinates(), ac.getYCoordinates())));
WebElement submitButton = driver.findElement(By.id(Constants.TA));
submitButton.click();
WebElement sndAttackSubmitButton = driver.findElement(By.name(Constants.SBM));
WebElement span = driver.findElement(By.className(Constants.CLASSNAME_TIME));
long duration = Long.parseLong(span.getAttribute(Constants.ATTRIBUTE_DURATION));
sndAttackSubmitButton.click();
ac.setStartTime(DateUtil.getActualServerTime());
ac.setDurationInSeconds(duration*1000);
ac.setTurnBackTime(ac.getStartTime()+ac.getDurationInSeconds());
}
}
}
}
}}
如您所见,我已将Thread.start()方法包装到Throwables和Exceptions的try-catch中,但如果线程无缘无故停止,我就不会获得任何Stacktrace。我期待StackOverFlow错误,但我没有抓到任何东西。
我的线程正在运行的循环数量是非常不同的。有时它会在12或之后停止,然后在370或59之后停止。所有值都是示例 - 每次都不同。
你有什么想法我做错了吗?
提前致谢!
答案 0 :(得分:1)
您需要检查run()
类的Thread
方法中的异常。
在调用start()
方法之后,创建的线程有自己的堆栈,这与主线程的堆栈不同,在那里调用start()
方法。
因此,与run()
方法相关的catch
语句将无法看到线程的start()
方法中抛出的异常。
答案 1 :(得分:1)
正如@Immibis在评论中所提到的那样,thread.start()
周围没有任何意义可以捕捉异常,因为它会立即返回。
检查异常的一种方法是使用UncaughtExceptionHandler
,如下所示:
Thread run = new Thread(action);
run.setUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
e.printStackTrace();
}
}
);
run.start();
答案 2 :(得分:1)
我已经将SystemOut放在每个代码行的后面,并在25次运行后计算出来并冻结了两个可能的代码行,其中线程停止工作:
两个语句都使用我的DateUtil.getActualServerTime()
方法,如下所示:
public static long getActualServerTime() {
String TIME_SERVER = "de.pool.ntp.org";
NTPUDPClient timeClient = new NTPUDPClient();
InetAddress inetAddress;
long returnTime = 0;
try {
inetAddress = InetAddress.getByName(TIME_SERVER);
TimeInfo timeInfo = timeClient.getTime(inetAddress);
returnTime = timeInfo.getMessage().getTransmitTimeStamp().getTime();
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable t) {
t.printStackTrace();
}
return returnTime;
}
我正在使用apache.commons.net lib。
如果我只是回来了
Date d = new Date(); return d.getTime();
我的线程可以正常工作约60.000循环,直到我手动停止它。
我也不会在这里得到异常或Throwable。我说在特定时间或类似时间内对时间服务器的最大请求量。我现在无法在网站上找到它。
答案 3 :(得分:0)
我也遇到同样的问题,我的线程被终止,没有任何异常/可抛出。
我有一个用于接受套接字的线程(nio,但为阻塞模式)。如果套接字以较慢的速度接收请求,但一次接收大量请求,则线程停止。 >
我在linux中更改了一些选项,例如mem [net.ipv4.tcp_rmem,net.core.wmem_default,net.ipv4.tcp_mem],可能是为此目的吗?