簡體   English   中英

不進行調試或打印時Java凍結

[英]Java freeze when not debugging or printing

我創建了一個簡單的最接近點算法應用程序,並帶有用於學校作業的漂亮UI。

問題是,當我停止重新運行算法時,出現了非常奇怪的凍結。 僅當我出於某種原因未調試且未編寫控制台輸出時,才會發生這種情況。

當我單擊按鈕再次運行算法時,第一次運行應該停止計算。 但是由於某種原因,它僅在我調試或寫入控制台時才這樣做,而在其他情況下,它只是完成了計算。 凍結本身非常明顯,因為我正在GUI線程上執行thread.join() ,但是算法沒有中斷的事實有點奇怪。

這是算法類:

public class Bruteforce extends Algorithm
{

    public Bruteforce( AlgorithmListener listener )
    {
        super( listener );
    }

    public void runAlgorithm()
    {
        EditablePair pair = new EditablePair();

        long startTime = System.currentTimeMillis();

        for ( int i = 0; i < pointlist.size() - 1 && keepRunning; i++ )
        {
            // Uncomment next line or run in debug and freeze doesn't happen
            //System.out.print( (keepRunning ? 1 : 0) );

            Point pi = pointlist.get( i );
            for ( int j = i + 1; j < pointlist.size() && keepRunning; j++ )
            {
                Point pj = pointlist.get( j );

                long d = pi.calculateSquaredDistanceTo( pj );

                if ( d < pair.distance || pair.distance == -1 )
                {
                    pair.distance = d;
                    pair.a = pi;
                    pair.b = pj;
                }
            }
        }

        int calculationtime = (int) ( System.currentTimeMillis() - startTime );
        if(!keepRunning)
            listener.onCalculated( null , -1 , -1 );
        listener.onCalculated( new Pair( pair ) , calculationtime , 0 );
    }
}

算法超類:

public abstract class Algorithm implements Runnable
{   
    public boolean visualizeOutput = false;

    protected AlgorithmListener listener;
    protected boolean keepRunning;
    protected Thread thread;

    private ArrayList<Point> tmpList;
    protected ArrayList<Point> pointlist;

    public Algorithm(AlgorithmListener listener)
    {
        this.listener = listener;
    }

    public void process(ArrayList<Point> pointlist)
    {
        System.out.println("Pre Start 1");
        tmpList = pointlist;
        System.out.println("Pre Start 2");
        listener.onStatusChanged( "Cancelling Previous Run..." );
        stopAndJoin();
        System.out.println("Pre Start 3");
        start();
    }

    public void start()
    {
        keepRunning = true;

        thread = new Thread(this);
        System.out.println("Post Start 1");
        thread.start();
        System.out.println("Post Start 2");
    }

    public void run()
    {
        System.out.println("Pre Run 1");
        listener.onStatusChanged( "Copying Point List..." );
        this.pointlist = new ArrayList<>(tmpList);
        System.out.println("Pre Run 2");
        listener.onStatusChanged( "Calculating..." );
        System.out.println("Pre Run 3");
        runAlgorithm();
        System.out.println("Post Run 1");
    }

    public abstract void runAlgorithm();

    public void stop()
    {
        keepRunning = false;
    }

    public void stopAndJoin()
    {
        stop();
        if(thread != null)
            try
            {
                thread.join();
            }
            catch( InterruptedException e )
            {
                e.printStackTrace();
            }
    }
}

僅當您在50.000+點上運行並在首次計算開始后再次按下按鈕時,該參數才值得注意

控制台輸出

Pre Start 1
Pre Start 2
Pre Start 3
Post Start 1
Post Start 2
Pre Run 1
Pre Run 2
Pre Run 3
Pre Start 1
Pre Start 2

UI凍結,直到完成計算,然后再次運行

([43768, 37240], [43769, 37240]) Distance = 1
Post Run 1
Pre Start 3
Post Start 1
Post Start 2
Pre Run 1
Pre Run 2
Pre Run 3
([43768, 37240], [43769, 37240]) Distance = 1
Post Run 1

我不知道為什么會這樣以及如何預防。

我自己沒有測試過,但是keepRunning是這可能是因為您的變量keepRunning是陳舊的。 如果正在從不同線程訪問此變量,則應真正使它volatile以確保可以從不同線程正確訪問它。

所以改變這個:

protected boolean keepRunning;

對此:

protected volatile boolean keepRunning;

欲了解更多信息,請看這里

暫無
暫無

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

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