如何正确处理Threads的输出? java的

时间:2011-03-03 14:57:55

标签: java multithreading progress-bar

我尝试用另一个线程处理不同runnables的输出。首先,我将所有runnables添加到一个集合中并尝试触发它们的进度,并将其保存到与该类别相关的地图中。类别是每个可运行的标识符。每个类别只能存在一个runnable。

之后我尝试在stdout的进度条中写出输出。但每次都是空的(0%)。奇怪的是,当我在Eclipse中进行调试时,一步一步,进度条似乎正常工作。我找不到问题,也许是时间问题或其他问题。 有人能说出我做错了吗?

如果有人知道更好的方法来处理不同线程的输出,请告诉我。我肯定会很高兴。

提前感谢您的帮助。

这是我的WriterThread:

public class WriterT extends Thread {

Set<Runnable> my_runnables = new HashSet<Runnable>();
Map<String, Integer> all_runnable_progress = new HashMap<String, Integer>();

public WriterT() {

}


public void add(Runnable r) {
    my_runnables.add(r);
}


public void run() {

    if(!my_runnables.isEmpty()) {

        int progress = 0;

        while(true) {
            for(Runnable r : my_runnables) {
                if(r instanceof Verify_TestRun) {
                    Verify_TestRun run = (Verify_TestRun)r;
                    progress = run.get_progress();
                    all_runnable_progress.put(run.get_category(), progress);
                }
            }

            if(progress <= 100) {
                print_progress();
            } else {
                break;
            }

            try {
                Thread.sleep(150);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}


private void print_progress() {

    StringBuilder str_builder = new StringBuilder();

    for(String cat : all_runnable_progress.keySet()) {

        int percent = all_runnable_progress.get(cat);

        str_builder.append(cat + "\t[");
        for(int i = 0; i < 25; i++){
            if( i < (percent/4)){
                str_builder.append("=");
            }else{
                str_builder.append(" ");
            }
        }

        str_builder.append("] " + percent + "%" + "\t");
    }

    System.out.print("\r" + str_builder.toString());
}

}

2 个答案:

答案 0 :(得分:1)

我认为这可能是问题所在:

progress = run.get_progress();

根据上下文,progress最终会以Verify_RunTest返回的 last 值结束,但我怀疑你的意思是总和 of the values。

(顺便说一句 - Verify_RunTest是不好的风格。它应该是VerifyRunTest。)

答案 1 :(得分:1)

更新新信息后的答案

因此,如果我理解正确,您想要检查您正在跟踪的每个测试运行,看看它们是否仍然在运行,即进度小于100并打印进度,只要它们不是全部完成

首先,您需要考虑Stephen C在他的回答中所说的内容 - 您(可能)想要总结每个测试运行的进度值。然后,检查每次测试运行的总和是否小于100。如果是这样,至少有一次测试运行仍在进行中,您打印进度并保持循环。如果你发现每次试运行的总和都是100,那么你就完成了。您最后一次打印进度以更新输出以反映每个输出100%,然后从循环中断。

以下是我建议的实现,它会对您的代码进行细微更改:

public void run() {
    if(!my_runnables.isEmpty()) {

        int progress = 0;

        while(true) {
            for(Runnable r : my_runnables) {
                if(r instanceof Verify_TestRun) {
                    Verify_TestRun run = (Verify_TestRun)r;
                    //change #1 - sum up the progress value of each test
                    progress += run.get_progress();
                    all_runnable_progress.put(run.get_category(), progress);
                }
            }

            //change #2 - break when all done
            if(progress < (100 * my_runnables.size()) ) { 
                //check if tests are still running i.e. there are test runs with progress < 100
                print_progress();
            } else {
                //otherwise print one last status (to update all status' to 100%) before stopping the loop
                print_progress();
                break;
            }

            try {
                Thread.sleep(150);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

不应在for循环中检查progress吗?您现在正在做的是迭代所有Runnable并将progress设置为进度值并将其添加到地图中。但随后你会立即转到下一个Runnable。最终结果是,离开循环后progress的值是您处理的最后Runnable的值。