代码之家  ›  专栏  ›  技术社区  ›  Nicola Bernardi

在Java中使用同步,如果乐器是同一子类的实例,则不允许它们一起演奏

  •  1
  • Nicola Bernardi  · 技术社区  · 7 年前

    我创建了三个抽象类来划分工具:String、Wind、Arc(每一个都扩展了Thread并指定run()方法)。我的乐器是这三种乐器的子类。没有任何子类重写run()方法)。 我希望只有一种超一流的乐器(弦、风、弧)可以同时演奏。不超过一个。我该怎么做?

    重新编辑2018年2月9日上午08:46
    谢谢你,米罗。但我还是有问题。在这里,我发布了一个类和使用它时的主类。谁能告诉我怎么修理?

    Archi类

    package strumenti.archi;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import strumenti.Sound;
    import sun.audio.AudioPlayer;
    import sun.audio.AudioStream;
    
    
    public class Archi extends Thread{
        String soundFileName;
    
        public Archi(String soundFileName){
            this.soundFileName = soundFileName;
        }
    
        private static boolean canPlay = true;
        private static Object playLock = new Object();
    
        @Override
        public void run() {
            checkPlayable();
            try {
                // your code
                play();
            }
            finally { // If a exception happens(or not) during the execution of the code block above, lock must be released.
                synchronized (playLock) {
                    canPlay = true; // enable playing for others
                    playLock.notifyAll(); // wake up others
                }
            }
    
        }
    
        /*
         * This is used to get the lock for the first one to come. Makes other ones wait.
         */
        private static void checkPlayable() { 
            synchronized (playLock) {
                while(!canPlay) {
                    try {
                        playLock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                canPlay = false;
            }
        }
    
        public synchronized void play(){  
            try {
                InputStream in = new FileInputStream(soundFileName);
    
                // create an audiostream from the inputstream
                AudioStream audioStream = new AudioStream(in);
    
                // play the audio clip with the audioplayer class
                AudioPlayer.player.start(audioStream);
            } catch (Exception ex) {
                System.err.println("Cannot play sound.");
                System.exit(0);
            }
       }
    
    
    }
    

    主要类别

    package orchestra;
    
    import strumenti.archi.*;
    
    public class Orchestra {
    
        public static synchronized void main(String[] args) {
    
            Thread[] strumenti = new Thread[3];
            strumenti[0] = new Archi("sample\\viola.wav");
            strumenti[1] = new Archi("sample\\cello.wav");
            strumenti[2] = new Archi("sample\\violino.wav");
            for(Thread t:strumenti){
                t.start();
            }
            //you should listen the three audio file one after the other
            //but it doesn't work
        }
    
    }
    

    问题已解决。线程必须等待音频剪辑完成。

    1 回复  |  直到 7 年前
        1
  •  1
  •   miskender    7 年前

    我没有看到您的代码,但如果我理解正确,您可以在这种情况下使用静态锁。下面的代码适用于单个仪表母级。此代码使同一时间只有一个乐器父乐器在演奏,一个乐器演奏完后,等待的乐器将逐一演奏。

    private static boolean canPlay = true;
    private static Object playLock = new Object();
    
    @Override
    public void run() {
        checkPlayable();
    
        try {
            // your code
        }
        finally { // If a exception happens(or not) during the execution of the code block above, lock must be released.
            synchronized (playLock) {
                canPlay = true; // enable playing for others
                playLock.notifyAll(); // wake up others
            }
        }
    
    }
    
    /*
     * This is used to get the lock for the first one to come. Makes other ones wait.
     */
    private static void checkPlayable() { 
        synchronized (playLock) {
            while(!canPlay) {
                try {
                    playLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            canPlay = false;
        }
    
    }