入梦叶 2017-10-16 15:38 采纳率: 66.7%
浏览 2694
已采纳

[问题已解决] java AudioClip播放的卡顿问题

问题已经解决,大家不用回答了。。。见一楼评论

我的程序里需要播放很多个短的声音片段,运行中偶尔会出现几秒钟的卡顿没有声音,一两秒之后突然所有卡住的声音一起出来。。我一开始怀疑是线程之间冲突了,然后用cachedthreadpool来管理,然而问题依旧,而且通过监测线程池的状态发现问题在于某一个时刻其中一个线程执行到ac.play时卡住了,于是线程池收到下一个播放任务时不得不开启新的线程,线程池中的线程数量也不断累积但是都卡在执行ac.play这一步,过了一两秒突然所有线程的“阻塞”都通了,声音也同时播放出来。

不知道问题的症结到底在哪里,尝试了很长时间一直没有解决,非常苦恼。。。

 import java.applet.Applet;
import java.applet.AudioClip;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SoundEffect implements Runnable {
    private static final ExecutorService exec = Executors.newCachedThreadPool();
    private static final int dulplinum = 10;
    private static AudioClip[] 
            ac1 = new AudioClip[dulplinum],
            ac2 = new AudioClip[dulplinum],
            ac3 = new AudioClip[dulplinum],
            ac4 = new AudioClip[dulplinum],
            ac5 = new AudioClip[dulplinum],
            ac6 = new AudioClip[dulplinum],
            ac7 = new AudioClip[dulplinum],
            ac8 = new AudioClip[dulplinum],
            ac9 = new AudioClip[dulplinum],
            ac10 = new AudioClip[dulplinum],
            ac11 = new AudioClip[dulplinum];
    private static AudioClip[][] acarray = {ac1,ac2,ac3,ac4,ac5,ac6,ac7,ac8,ac9,ac10,ac11};
    private static String[] acname = {"move","lock","select","hold","rotate","decide","levelup","erase","lose","harddrop","pause"};
    static{
        for(int i=0;i<acarray.length;i++) {
            for(int j=0;j<dulplinum;j++) {
                acarray[i][j] = Applet.newAudioClip(SoundEffect.class.getResource("/resources/sound/"+acname[i]+".wav"));
            }
        }
    }
    private static Integer[] cursorArray = {0,0,0,0,0,0,0,0,0,0,0};
    private int cursor;
    private AudioClip ac;
    private String name;

    SoundEffect(String name) {
        this.name = name;
    }

    public void run() {
        switch(name) {
        case "move":    cursor = 0; break;
        case "lock":    cursor = 1; break;
        case "select":  cursor = 2; break;
        case "hold":    cursor = 3; break;
        case "rotate":  cursor = 4; break;
        case "decide":  cursor = 5; break;
        case "levelup": cursor = 6; break;
        case "erase":   cursor = 7; break;
        case "lose":    cursor = 8; break;
        case "harddrop":cursor = 9; break;
        case "pause":   cursor = 10;break;
        }
        ac = cursor2ac(cursor);
        ac.play();
    }

    private static synchronized AudioClip cursor2ac(int cursor) {
        cursorArray[cursor] = (cursorArray[cursor]+1)%dulplinum;
        return acarray[cursor][cursorArray[cursor]];
    }

    public static void playSound(String name) {
        exec.execute(new SoundEffect(name));
    }
}

稍微解释一下,dulplinum=10 的意思是每个ac都缓存10份,每一个新的进程会循环地从4份中取出其中一个来播放。
下面这个就是卡顿发生时,相关信息输出到控制台的结果。

 [time:    0] Sound: move 第0个副本
[time:  192] play sound move
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 2, active threads = 1, queued tasks = 0, completed tasks = 439]
[time:    0] Sound: move 第1个副本
[time:  197] play sound move
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 2, active threads = 1, queued tasks = 0, completed tasks = 440]
[time:    0] Sound: move 第2个副本
[time:   91] play sound rotate
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 440]
[time:    0] Sound: rotate 第1个副本
[time:  272] play sound move
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 440]
[time:    1] Sound: move 第3个副本
[time:  303] play sound move
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 4, active threads = 4, queued tasks = 0, completed tasks = 440]
[time:    0] Sound: move 第4个副本
[time:   48] play sound harddrop
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 5, active threads = 5, queued tasks = 0, completed tasks = 440]
[time:    0] Sound: harddrop 第8个副本
[time:   50] play sound lock
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 6, active threads = 6, queued tasks = 0, completed tasks = 440]
[time:    0] Sound: lock 第8个副本
[time:  182] play sound move
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 7, active threads = 7, queued tasks = 0, completed tasks = 440]
[time:    0] Sound: move 第5个副本
[time:  120] play sound move
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 8, active threads = 8, queued tasks = 0, completed tasks = 440]
[time:    0] Sound: move 第6个副本
[time:  216] play sound rotate
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 9, active threads = 9, queued tasks = 0, completed tasks = 440]
[time:    0] Sound: rotate 第2个副本
[time: 1528] play sound pause
[time:    0] java.util.concurrent.ThreadPoolExecutor@22d9a984[Running, pool size = 9, active threads = 1, queued tasks = 0, completed tasks = 449]
[time:    0] Sound: pause 第3个副本
[time:21429] bgm end
  • 写回答

1条回答 默认 最新

  • 入梦叶 2017-10-18 10:11
    关注

    我自己已经解决问题了。。换成sun.audio类来完成播放没有任何问题,并且完全不需要用线程管理的方式来处理,看来还是audioclip的问题。。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥20 为什么我写出来的绘图程序是这样的,有没有lao哥改一下
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥200 关于#c++#的问题,请各位专家解答!网站的邀请码
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号