我正在 java 中制作命令行音乐播放器,我的 'skip' 按钮有时会跳过不止一次

I'm making a command line music player in java, and my 'skip' button is sometimes skipping more than once

所以,基本上,我的代码目前只是从命令行接收一个参数,即播放列表中要播放所有波形文件的文件夹。我有另一个接受用户输入的线程。当用户输入 'skip' 时,它将继续执行项目的 for 循环。一切正常,但是,如果我键入 skip 并按回车键,有时它会跳过两次。我认为它与线程业务有关。这是我的代码。

 package com.thechief.music;

 import java.io.File;
 import java.io.FilenameFilter;
 import java.util.Scanner;

 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
 import javax.sound.sampled.Clip;

 public class Player {

public static int index = 0; // The current clip playing
public static Clip[] clip;

public static void main(String[] args) throws Exception {
    Scanner scanner = new Scanner(System.in);

    FilenameFilter textFilter = new FilenameFilter() {
        public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(".wav");
        }
    };

    File[] files = new File(args[0]).listFiles(textFilter);
    clip = new Clip[files.length];

    Runnable b = new Runnable() {
        public void run() {
            while (true) {
                String command = scanner.next();
                if (command.equals("skip")) {
                    getCurrentClip().stop();
                } else if (command.equals("back")) {
                    getCurrentClip().stop();
                    if (index > 0) {
                        index -= 2;
                    } else {
                        System.out.println("Cannot go back further than the first item.");
                    }
                }
            }
        }
    };
    Thread second = new Thread(b);
    second.start();

    for (index = 0; index < clip.length; index++) {
        if (index < 0) index = 0;
        clip[index] = AudioSystem.getClip();
        if (index < 0) index = 0;
        AudioInputStream ais = AudioSystem.getAudioInputStream(files[index]);
        if (!getCurrentClip().isOpen()) {
            getCurrentClip().open(ais);
        } else {
            getCurrentClip().close();
            getCurrentClip().open(ais);
        }

        getCurrentClip().start();

        System.out.println("Now Playing: " + files[index].getName() + ", Time Left: "
                + (getCurrentClip().getMicrosecondLength() / 1000000.f) + " seconds.");

        while (getCurrentClip().getMicrosecondLength() != getCurrentClip().getMicrosecondPosition()
                || getCurrentClip().isActive()) {
            if (!getCurrentClip().isActive()) {
                break;
            }
        }
    }

    System.out.println("Playlist completed.");

    scanner.close();
    second.join();
}

public static Clip getCurrentClip() {
    return clip[index];
}
 }

这里:

public static int index = 0; // The current clip playing

该索引字段被多个线程使用和更新。这意味着:任何事情都可能发生。

第一步:在这里使用 AtomicInteger 而不是 int

真正的答案当然是:你必须研究你在做什么。只是在 不知道 的情况下在这里或那里添加 new Thread().start() 并理解你在做什么,只不过是 运行 进入各种不可预测行为的秘诀。这非常简单:当可变数据在多个线程之间共享时,您绝对必须确保采取必要的预防措施。

提供更多指导:防止 if (index < 0) index = 0; 之类的事情启用 races

意思是:例如一个线程看到index=1,然后将index变为0。但同时另一个线程试图读取index,并使用了错误的中间内容。

当您将该索引转换为 AtomicInteger 时,您可以开始执行以下操作:

synchronized(index) {
  if (index ...
    index = ...
}

例如。