2

私は非常に厄介な問題を抱えており、これを自分で修正することはできません。

スレッドを開始して終了するためのボタンが 2 つだけの単純な JavaFX シーンがあります。この場合、スレッドをうまく機能させることができないため、停止アクションは関係ありません。actionListener は次のようになります。

EDIT1:問題を理解しました。これはスレッド固有ではなく、TimeServerに対するリクエストです。ここを見てください:回答
これに回答したり、質問を読んだりした皆さんに感謝します!:)

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 を使用して、Web サイトでのクリックを自動化しています。

私の 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 で停止することもあります。すべての値は例であり、毎回異なります。

私が間違っていることについて何かアイデアはありますか?

前もって感謝します!

4

4 に答える 4

1

クラスのrun()メソッド内で例外をチェックする必要があります。Thread

メソッドを呼び出した後、start()作成されたスレッドは独自のスタックを持ちます。これは、start()メソッドが呼び出されるメイン スレッドのスタックとは異なります。

したがって、スレッドのメソッド内でスローされた例外は、メソッドに関連するステートメントrun()には表示されません。catchstart()

于 2015-05-28T00:24:36.277 に答える
1

コメントで@Immibisが述べたように、例外はthread.start()すぐに返されるため、例外をキャッチする意味はありません。

例外を検査する 1 つの方法はUncaughtExceptionHandler、次のようなを使用することです。

Thread run = new Thread(action);
run.setUncaughtExceptionHandler(
    new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            e.printStackTrace();
        }
    }
);
run.start();
于 2015-05-28T03:46:43.767 に答える
1

OK guys, I've figuered the problem out. It's not thread specific, sorry for that, but I've learned almost a bit more about threads because of your answers :) Thanks to everyone of you!

I've put SystemOuts behind every single codeline and figured out after 25 runs and freezes there are two possible codelines where thread stops working:

Both statements use my DateUtil.getActualServerTime() Method which looks as follows: ​

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;
}

I'm using the apache.commons.net lib for that. If I'm just return a Date d = new Date(); return d.getTime(); my thread works fine for about 60.000 loops until I've stopped it manually.

I don't get an Exception or Throwable here as well. I'd say theres a maximum amount of request against the time server in a specific time or something like that. I can't figure it out on the Website right now.

于 2015-05-28T12:32:22.913 に答える
0

私も同じ問題を抱えています。私のスレッドは例外/スロー可能なしで終了します。

ソケットを受け入れるためのスレッド(nio、ただしブロッキングモード)があります。これは、ソケットが低速でリクエストを受信する場合はうまく機能しますが、一度に多くのリクエストを受信すると、スレッドが停止します。

mem [net.ipv4.tcp_rmem, net.core.wmem_default, net.ipv4.tcp_mem] のような Linux のいくつかのオプションを変更しましたが、これが原因でしょうか?

于 2020-08-14T07:08:45.083 に答える