簡體   English   中英

如何在Java中創建線程控制台控制台?

[英]How to create a threaded console progress bar in Java?

我正在嘗試用Java創建一個可運行的進度欄程序,以便它可以支持控制台和GUI應用程序。

這個想法是使用線程來提供當前的進度信息,但是似乎線程代碼無法正常工作。 並發對我來說太新了。

我希望它每次向上移動一次,而不是在進度條趕上之前過早地完成循環。 我猜問題出在時間上嗎?

[=====>                                            ] 10%  1
2
3
4
5
6
7
8
9
10

[==================================================] 100%  

有人可以告訴我我出了什么問題嗎?

主要代號

package console;
import java.util.ArrayList;
import console.ProgressThread;

public class ConsoleProgressBar
{
    private static final long REFRESH_DELAY = 50;
    private ProgressValue progress;
    private ProgressThread target;
    private Thread thread;

    protected static class ProgressValue
    {
        protected long total = 0;
        protected long current = 0;

        protected ProgressValue(long n)
        {
            total = n;
        }

        protected synchronized void setMaxTotal(long n)
        {
            total = n;
        }

        protected synchronized void stepBy(long n)
        {
            current = current + n;

            if (current > total) total = current;
        }

        protected synchronized void stepTo(long n)
        {
            current = n;

            if (current > total) total = current;
        }

        protected synchronized long getCurrent()
        {
            return current;
        }

        protected synchronized long getTotal()
        {
            return total;
        }
    }

    public ConsoleProgressBar(long totalItem)
    {
        this(totalItem, REFRESH_DELAY);
    }

    public ConsoleProgressBar(long totalItem, long refreshDelay)
    {
        progress = new ProgressValue(totalItem);
        target = new ProgressThread(progress, refreshDelay);
    }

    public void start()
    {
        thread = new Thread(target);
        thread.start();
    }

    public void stepBy(long n)
    {
        progress.stepBy(n);
    }

    public void stepTo(long n)
    {
        progress.stepTo(n);
    }

    public void step()
    {
        progress.stepBy(1);
    }

    public void setMaxTotal(long n)
    {
        progress.setMaxTotal(n);
    }

    public void stop()
    {
        target.terminate();

        try
        {
            thread.join();
        }

        catch (InterruptedException ex)
        {
        }
    }

    public long getCurrent()
    {
        return progress.getCurrent();
    }

    public long getTotal()
    {
        return progress.getTotal();
    }

    public static void main(String[] args)
    {
        ArrayList<Integer> test = new ArrayList<>();
        ConsoleProgressBar bar = new ConsoleProgressBar(10, 50);

        bar.start();

        for (int i = 0; i < 10; i++)
        {
            int sum = i + 5;

            test.add(sum);

            bar.step();

            System.out.format("%s%n", bar.getCurrent());
        }

        bar.stop();
    }
}

線程代碼

package console;

import console.ConsoleProgressBar.ProgressValue;

public class ProgressThread implements Runnable
{
    private static final int WIDTH = 50;
    private volatile boolean terminated;
    private ProgressValue progressRef;
    private long timeMS;

    public ProgressThread(ProgressValue ref, long refreshDelay)
    {
        progressRef = ref;
        timeMS = refreshDelay;
        terminated = false;
    }

    private void refreshProgressBar()
    {
        StringBuilder sb = new StringBuilder("\r[");
        int percent = (int) Math.floor(100.0 * progressRef.current / progressRef.total);

        for (int i = 0; i < WIDTH; i++)
        {
            if (i < (percent / 2)) sb.append("=");
            else if (i == (percent / 2)) sb.append(">");
            else sb.append(" ");
        }

        sb.append("] %s  ");

        if (percent >= 100) sb.append("%n");

        System.out.printf(sb.toString(), percent + "%");
    }

    void terminate()
    {
        terminated = true;
    }

    public void run()
    {
        try
        {
            while (terminated == false)
            {
                refreshProgressBar();
                Thread.sleep(timeMS);
            }

            refreshProgressBar();
        }

        catch (InterruptedException exc)
        {
        }
    }
}

當您僅想完成一項任務時,為什么需要多線程應用程序?

盡管如此,要實現所需的目標,我建議將執行完全移入線程類或主類。

如果主應用程序將要運行其他程序,那么理想情況下,您應將執行放在線程類中。 但是在這里,我已將執行放入主類。 它也可以很容易地進入線程類。

舉例來說,我在ProgressThread編輯了run()就是這樣,

public void run()
{
    while( terminated )
    {
    }
}

然后我在ConsoleProgressBar編輯了main

public static void main(String[] args)
{
    ArrayList<Integer> test = new ArrayList<>();
    ConsoleProgressBar bar = new ConsoleProgressBar(10, 50);

    bar.start();

    for (int i = 0; i <= 10; i++)
    {
        int sum = i + 5;

        test.add(sum);

        bar.refreshProgressBar();
        System.out.format( "%s", bar.getCurrent() );
        bar.step();
        bar.sleep( 1000 );
    }

    bar.stop();
}

請注意,我將方法sleep( int n )refreshProgressBar()到bar中,以便可以調用線程方法,類似於您對bar.start()bar.stop()

為清楚起見,僅出於示例目的,在ProgressThread我將refreshProgressBar更改為public ,並添加了以下內容:

void sleep( int n )
{
    try
    {
        Thread.sleep( n );
    }
    catch( InterruptedException ie )
    {
        ie.printStackTrace();
    }
}

以及以下ConsoleProgressBar

private void sleep( int n )
{
    target.sleep( n );
}

private void refreshProgressBar()
{
    target.refreshProgressBar();

}

輸出(每行打印間隔為一秒)為:

[>                                                 ] 0%  0
[=====>                                            ] 10%  1
[==========>                                       ] 20%  2
[===============>                                  ] 30%  3
[====================>                             ] 40%  4
[=========================>                        ] 50%  5
[==============================>                   ] 60%  6
[===================================>              ] 70%  7
[========================================>         ] 80%  8
[=============================================>    ] 90%  9
[==================================================] 100%  10

不確定這是否是您要查找的內容,但我建議將執行結果放到一個地方。

暫無
暫無

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

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