0

スレッドを使用して、長い操作 (大きなファイルのバッチに対して md5sums を生成する) を実行しているときに、Java の CLI に進行状況バーを表示しようとしています。

私は少しコードを書いて動作しますが、スレッドを正しく使用しているかどうかを知りたいのですが、私はこれにかなり慣れていません。

2 つのクラス ファイルがProgressThreadTest.javaあり、CountToABillion.java

CountToABillion.java:

public class CountToABillion implements Runnable {

    double count = 0;

    public void echoCount() {
        System.out.println(count);
    }

    @Override
    public void run() {     
        for (double x=0;x<1000000000;x++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            count = x;
            echoCount();
        }       
    }   
}

ProgressThreadTest.java:

public class ProgressThreadTest {

    public static void main(String[] args) throws InterruptedException {

        Thread doCount=new Thread(new CountToABillion());
        doCount.start();
    }   
}

期待どおりに機能し、コマンドラインで上向きにカウントされます。

これがスレッドを行う良い方法であるかどうかについて、何かコメントはありますか?

また、カウント ループで進行状況を更新しているため、10ms ごとに更新されます。毎秒 1 回だけカウントを出力するようにコードを変更するにはどうすればよいですか?

4

4 に答える 4

2

使用するjavax.swing.Timerのがおそらくより簡単な解決策です:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;

public class CountToABillion implements Runnable {

    double count = 0;
    Timer progressTimer;

    public void echoCount() {
        System.out.println(count);
    }

    @Override
    public void run() {
        progressTimer = new Timer(1000, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                echoCount();
            }
        });
        progressTimer.setRepeats(true);
        progressTimer.start();

        for (double x=0;x<1000000000;x++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            count = x;
        }
        progressTimer.stop();
    }
}

使用java.util.concurrent.ScheduledThreadPoolExecutorは、より優れたスケーラブルなソリューションです。

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CountToABillion implements Runnable {

    double count = 0;
    ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);

    public void echoCount() {
        System.out.println(count);
    }

    @Override
    public void run() {
        Runnable task = new Runnable() {
            public void run() {
                echoCount();
            }
        };
        exec.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS);

        for (double x=0;x<1000000000;x++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            count = x;
        }
        exec.shutdownNow();
    }
}
于 2013-07-05T12:18:51.903 に答える
1
long last=0;
@Override
public void run() {     
    for (double x=0;x<1000000000;x++) {
        try {
            doWork();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        count = x;
        if((System.currentTimeMillis()-last)>=1000) //post every second
        {
            last=System.currentTimeMillis();
            echoCount();
        }
    }       
} 

これは、「作業」に 1 秒以上かからないと仮定して、1 秒ごとにカウントを出力します。

于 2013-07-05T12:15:25.763 に答える
1
@Override
public void run() {     
    for (int i = 0; i < 1000000000; i++) {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count = i;

        if(i % 100 == 0) {
            echoCount();
        }
    }
}

を使用して、残りの値なしで 100 で割り切れるi % 100 == 0かどうかを確認しています。iその場合は、1000ms である 10ms を 100 回実行したことを意味します。echoCountt()したがって、毎秒出力されます。

これは、スレッドを使用する適切な方法です。ただし、スレッドは 10000000 秒カウントされるまで実行され続けます。

補足として、for ループでは「x」の代わりに「i」を使用する必要があります。このように広く使用されており、経験豊富な Java 開発者にとっては読みやすいでしょう。

于 2013-07-05T12:08:34.763 に答える