簡體   English   中英

Java 線程在沒有異常/可拋出的情況下停止

[英]Java Thread stops without Exception/Throwable

我有一個非常煩人的問題,我無法自己解決這個問題。

我有一個簡單的 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 框架來自動化網站上的一些點擊。

我的 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 AND Exceptions 的 try-catch 中,但如果線程無故停止,我將不會得到任何 Stacktrace。 我預計會出現 StackOverFlow 錯誤,但我什么也沒發現。

我的線程工作的循環數量非常不同。 有時它在 12 點后停止,然后在 370 或 59 點后停止。所有值都是示例 - 每次都不同。

你有什么想法我做錯了嗎?

提前致謝!

您需要在Thread類的run()方法中檢查異常。

調用后start()方法,該線程創建的都有自己的堆棧,這是主線程,其中的堆棧不同start()方法是從調用。

因此,在線程的run()方法內拋出的異常對於與start()方法相關的catch語句將不可見。

正如@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();

好的,伙計們,我已經找到了問題所在。 這不是特定於線程的,很抱歉,但是由於您的回答,我幾乎學到了更多關於線程的知識:) 感謝大家!

我已經將 SystemOuts 放在每條代碼行后面,並在 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 庫。 如果我只是返回一個Date d = new Date(); return d.getTime(); Date d = new Date(); return d.getTime(); 我的線程可以正常工作大約 60.000 個循環,直到我手動停止它。

我在這里也沒有得到 Exception 或 Throwable 。 我會說在特定時間或類似時間對時間服務器的最大請求量。 我現在無法在網站上弄清楚。

我也有同樣的問題,我的線程在沒有任何異常/可拋出的情況下終止。

我有一個線程接受套接字(nio,但阻塞模式)。這很好用,如果套接字以慢速接收請求,但是當一次接收大量請求時,線程停止。

我在 linux 中更改了一些選項,例如 mem [net.ipv4.tcp_rmem, net.core.wmem_default, net.ipv4.tcp_mem],可能是為了這個?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM