我是丹麦的一名学生,正在尝试制作一个学校项目。我现在正在做的是一个读取器类,它接收一个字符串然后逐个字母地打印出来。
我做了一些研究,发现Thread.sleep(time)
完全按照我的要求去做。 但是在我使用它之后我发现它无法正常工作!我试着再研究一下,找到了一个名为ThreadPoolExecutor
的东西,但我可以弄清楚它是如何起作用的。
我的读者:
public class TextReader {
// Print method to print word by word from a string
public void wordByWord(String text) throws InterruptedException {
String[] words = text.split(" ");
for (int i = 0; i < words.length; i++) {
System.out.print(words[i] + " ");
Thread.sleep(250);
}
}
// Print method to print letter by letter from a string
public void letterByLetter(String text) throws InterruptedException {
String[] words = text.split(" ");
for (int i = 0; i < words.length; i++) {
String word = words[i] + " ";
char[] letters = (word.toCharArray());
for (int j = 0; j < letters.length; j++) {
System.out.print(letters[j]);
Thread.sleep(250); //so it does not print all the letters at once
}
}
}
}
Thread.sleep(time)
在我的情况下不起作用的原因是因为我需要打印到控制台并使用Thread.sleep(time)
它不像瀑布一样打印。它打印出我想要分解的字符串(时间低于250毫秒)或一些字母一次(250毫秒)或者只是如此慢,我无法看到它......(超过250毫秒)。我需要它快速平稳地运行!所以看起来有人在写它。
答案 0 :(得分:2)
我想我成功地重新创建了你的问题。每次延迟低于 205 ms 似乎都会导致更新问题。有时单词/字母不会出现,但在下一个时间间隔内会出现多个单词/字母。
这似乎是控制台I / O性能的限制(See this answer)。你真的无法做到这一点。如果您希望以这样的短暂,最小延迟输出文本,则需要编写自己的GUI(例如JavaFX)。这可能会解决性能问题。
答案 1 :(得分:1)
你正在做的是让一个线程在那个时候睡觉。这意味着在此之后线程将被解除阻塞,但是您没有考虑从另一个线程切换上下文的开销。 What you want is something more like this
答案 2 :(得分:1)
线程的sleep方法需要几毫秒来停止执行当前线程达指定的毫秒数。如果它很慢,你可以传递较少的MS,如果它很快,那么你可以增加时间。所以你可以根据需要进行调整。
ExecutorFramework是另一回事。 这是一种将可运行任务提交给ExecutorFramework管理的线程的方法。
答案 3 :(得分:0)
尝试ScheduledExecutorService
方法,似乎工作正常。有一些优化要做,有些箍要跳过等待预定的打印完成,但它似乎没有显示滞后(在我试过的两个控制台中 - Eclipse输出和Windows Bash )。
public class Output {
public static void main(String[] args) {
String toPrint = "Hello, my name is Voldemort, but few call me that.";
StringPrinter printer = new StringPrinter();
printer.print(toPrint, Output::byCharacter, 30);
System.out.println();
printer.print(toPrint, Output::byWord, 150);
}
private static List<String> byWord(String toSplit) {
Iterable<String> it = () -> new Scanner(toSplit);
return StreamSupport.stream(it.spliterator(), false).map(s -> s + " ").collect(Collectors.toList());
}
private static List<String> byCharacter(String toSplit) {
return toSplit.chars().mapToObj(i -> "" + (char) i).collect(Collectors.toList());
}
}
class StringPrinter implements Runnable {
// using an array to be most efficient
private String[] output;
private int currentIndex;
// the service providing the milliseconds delay
private ScheduledExecutorService printExecutor;
public void print(String toOutput, Function<String, List<String>> split, int delay) {
if (printExecutor != null) {
throw new IllegalStateException();
}
printExecutor = Executors.newSingleThreadScheduledExecutor();
List<String> list = split.apply(toOutput);
output = list.toArray(new String[list.size()]);
currentIndex = 0;
printExecutor.scheduleWithFixedDelay(this, 0, delay, TimeUnit.MILLISECONDS);
// wait until output has finished
synchronized (this) {
while (printExecutor != null)
try {
wait(); // wait for printing to be finished
} catch (InterruptedException e) {}
}
}
@Override
public void run() {
if (currentIndex < output.length) {
System.out.print(output[currentIndex++]);
} else {
// mark this print run as finished
printExecutor.shutdown();
printExecutor = null;
synchronized (this) { notifyAll(); }
}
}
}