0

残念ながら、スレッドを適切に設定する方法について、私はかなりよく理解していません。ここSO.SEと他のサイトの両方にこれに関するたくさんの情報があることは知っていますが、私が読んだことを私がしていることと正しく関連付けることができないようです.

私の問題は、一方が他方で除算される2つのパラメーターを取るメソッドがあることです。商 (結果) は、視覚的なプログレス バーを埋めるために使用されます。商が 1 になったら(readBytes/contentLength == 1)、進行状況バーがレイアウトから削除される前に、特定の時間待機するスレッド (推測) が必要です。プログレスバーに値を設定するために必要なすべてのコードと、それをビューから削除する方法を知っています。私の質問は、コンポーネントを削除するアクションがトリガーされる前に、たとえば 2000 ミリ秒待機させる方法です。

これはおそらく基本的なスレッドの知識ですが、私はそれに大きな問題を抱えています。

これまでのところ、次の2つのアプローチを試しました。

@Override
    public void updateProgress(long readBytes, long contentLength) {

        this.contentLength = contentLength;

        if(readBytes != 0 && contentLength != 0 && fileListItem != null)    {

            fileListItem.getProgressIndicator().setValue(readBytes/contentLength);

            synchronized (this) {
                while(readBytes/contentLength != 1) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    };
                    fileListItem.removeProgressIndicator();                 
                }
            }
        }

        if(!itemIsAdded)    {

            checkFileCompatibility(contentLength);

        }
    }

@Override
    public void updateProgress(long readBytes, long contentLength) {

        this.contentLength = contentLength;

        if(readBytes != 0 && contentLength != 0 && fileListItem != null)    {

            if(readBytes/contentLength == 1)    {
                Thread t = new Thread();
                t.start();
                try {
                    t.wait(2000);
                    fileListItem.removeProgressIndicator();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                t.interrupt();
            } else  {
                fileListItem.getProgressIndicator().setValue(readBytes/contentLength);
            }
        }

        if(!itemIsAdded)    {

            checkFileCompatibility(contentLength);

        }
    }

成功しませんでした。最初の例では、メイン スレッドが待機しているように見えますが、何も起こりません。2 番目の例では、t.wait(2000);. どうしたらいいのか途方に暮れています..

編集:ボヘミアンからの入力で、私はそれを機能させました。

@Override
    public void updateProgress(final long readBytes, final long contentLength) {

        this.contentLength = contentLength;

        if(readBytes != 0 && contentLength != 0 && fileListItem != null)    {

            if(!threadIsRunning)    {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        threadIsRunning = true;
                        while(!fileIsAdded) {
                            try {
                                Thread.sleep(2000);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                LOGGER.error(e.getMessage());
                                break;
                            }
                        }
                        fileListItem.removeProgressIndicator();
                        threadIsRunning = false;
                    }
                }).start();
            }

            fileListItem.getProgressIndicator().setValue(readBytes/contentLength);
            if(readBytes == contentLength)
                fileIsAdded = true;
        }

        if(!itemIsAdded)    {

            checkFileCompatibility(contentLength);

        }
    }

まだ片付けが必要ですが、基本は機能しています。

4

3 に答える 3

2

おそらく、SwingWorkerはあなたのタスクに適したツールです。Javadocには完全なコードサンプルがあります。メソッドに注意してください。これsetProgressは、プログレスバーを更新するのに理想的です。

必要なのがプログレスバーをクリアするための固定された2秒の遅延だけである場合は、スイングタイマーを使用します。マルチスレッドも含まれていません。指定された遅延の後に実行されるコールバックハンドラーを作成するだけです。

于 2012-06-28T11:05:05.057 に答える
1

メインスレッドを待たせません。スケーラブルではなく、GUI が不安定になるため、これは悪い習慣です。

代わりに、タイムアウト値といくつかのコールバックをワーカー スレッドに渡して、タイムアウトを超えたとき/作業が完了したときに実行します。そうすれば、メイン スレッドは自由にやりたいことに戻ることができます。

説明のためだけに、「完了」コールバックは次のようになります。

new Runnable() {
    public void run() {
        // code that hides the progress bar
    }
}

「タイムアウト」コールバックは次のようになります。

new Runnable() {
    public void run() {
        // code that displays an error message
    }
}

ところで、スレッドに何かをさせるには、Runnable も渡します。

new Thread(new Runnable() {
    public void run() {
        // code that runs when your thread starts
    }
}).start();
于 2012-06-28T10:31:25.543 に答える
1

本当に必要なのは

Thread.sleep(2000);

の代わりにwaitwaitスリープに使用できますが、その主な機能はスレッド間シグナリングであり、待機中のオブジェクトのロックが必要です。これは取得していないため、例外です。

編集:さらに調べてみると、あなたが正しくやっていないことに気づきました。runメソッドが関連付けられていないスレッドを作成しているだけです。

Thread t = new Thread();
t.start();

したがって、スレッドは何も実行していません。

スレッドを正しく設定する方法については、Java スレッド化チュートリアルを読むことをお勧めします: http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

于 2012-06-28T10:28:33.587 に答える