我正在尝试用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)
{
}
}
}
答案 0 :(得分:1)
为什么只需要一个你想要实现的任务就需要一个多线程应用程序?
尽管如此,为了达到你想要的目的,我建议你将执行完全转移到线程类或主类中。
如果主应用程序要运行其他东西,那么理想情况下你会将执行放在线程类中。但是在这里我把执行放到了主类中。它也可以轻松进入线程类。
例如,我在run()
中编辑了ProgressThread
就是这样,
public void run()
{
while( terminated )
{
}
}
我在main
中对此ConsoleProgressBar
进行了编辑,
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.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
不确定这是否是您要找的,但我建议将执行放在一个地方。