简体   繁体   English

我正在用Java制作命令行音乐播放器,而“跳过”按钮有时会跳过多次

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

So, basically, my code currently is just taking in one argument from the commmand line, which is the folder in which all of the wave files are to play in the playlist. 因此,基本上,我的代码当前仅从commmand行接受一个参数,该行是所有wave文件将在播放列表中播放的文件夹。 I have another thread which takes in user input. 我有另一个线程接受用户输入。 When the user inputs 'skip' it will continue through the for loop of items. 当用户输入“跳过”时,它将继续通过项目的for循环。 It all works fine, but, if i type skip, and hit enter, sometimes it skips twice. 一切正常,但是,如果我键入skip,然后按Enter,有时它会跳过两次。 I presume it has something to do with the threading business. 我认为这与线程业务有关。 Here's my code. 这是我的代码。

 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];
}
 }

Here: 这里:

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

That index field is used and updated by more than one thread. 该索引字段由多个线程使用和更新。 That means: anything can happen. 这意味着:任何事情都可能发生。

A first step: use AtomicInteger instead of int here. 第一步:在这里使用AtomicInteger而不是int

And the real answer of course: you have to research what you are doing. 当然,这是真正的答案:您必须研究自己在做什么。 Just adding new Thread().start() here or there without knowing and understanding what you are doing is a nothing but a recipe to run into all sorts of unpredictable behavior. 只是在这里或那里添加new Thread().start()而不知道和了解自己在做什么,只是导致各种不可预测行为的秘诀。 It is super simple: when mutable data is shared between multiple threads, then you absolutely must ensure that the necessary precautions are in place. 这非常简单:在多个线程之间共享可变数据时,您绝对必须确保采取必要的预防措施。

To give a bit more guidance: to prevent things like if (index < 0) index = 0; 给出更多指导:防止类似if (index < 0) index = 0; to enable races . 使种族

Meaning: one thread sees index=1 for example, and then turns index to 0. But at the same time, another thread tried to read index, and used wrong intermediate content. 含义:例如,一个线程看到index = 1,然后将index变为0。但是,与此同时,另一个线程试图读取index,并且使用了错误的中间内容。

When you turn that index into an AtomicInteger , you can start doing things like: 当您将该索引转换为AtomicInteger ,可以开始执行以下操作:

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

for example. 例如。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android:提高Music Player应用的效率 - Android: making a Music Player app more efficient 当我再按一次播放按钮,然后在mp3播放器中一次,我的应用程序崩溃 - when i hit play button more then once in my mp3 player my application crashes 在我运行音乐应用程序时如何停止默认音乐播放器 - How to stop default music player while I'm running my music app "我是 java\/coding 的新手,我的教授希望我创建一个计算数学函数的应用程序,但我一次只能做一个" - I'm new to java/coding and my professor wants me to create an application that calculates math functions but I can't do more than one at once 如何更改我的代码以允许我的回溯命令多次工作? - How can I alter my code to allow my retrace command to work more than once? Enum *似乎*被多次初始化,构造函数被多次调用。 如果我是对的,那为什么? - Enum *seems* to be initialized more than once, the constructor is called more than once. If I’m right, then why? 在我的Androidstudio音乐播放器中,暂停按钮问题 - In my Androidstudio music player pause button problem 在Java中仅单击一次按钮后如何从多个文本字段打印 - How i can print from more than one textfield after clicking the button just once in java Java exec命令提示符多于一行命令 - Java exec command prompt more than one line of command 如果多次调用此方法,为什么有时会给我一个错误 - Why does this method sometimes give me an error if I call it more than once
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM