入梦叶 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 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料