繁体   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