Simplified version of what I'm actually doing (triggering a buzzer sound when a timer expires), but this demonstrates my design well enough.
Once playback is started, Swing never needs to touch the audio clip again. I have been able to confirm that this code does play back the sound and does not block the event dispatch thread, but I want to make sure there isn't some other thread safety concern that I am unknowingly violating. Thanks!
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class TriggeringSoundTest extends JFrame
{
    private static final long serialVersionUID = -4573437469199690850L;
    private boolean soundPlaying = false;
    public TriggeringSoundTest()
    {
        JButton button = new JButton("Play Sound");
        button.addActionListener(e -> new Thread(() -> playBuzzer()).start());
        getContentPane().add(button);
    }
    private void playBuzzer()
    {
        URL url = getClass().getResource("resources/buzzer.wav");
        try (AudioInputStream stream = AudioSystem.getAudioInputStream(url); 
                Clip clip = AudioSystem.getClip())
        {
            clip.open(stream);
            clip.addLineListener(e -> {
                if (e.getType() == LineEvent.Type.STOP)
                    soundPlaying = false;
            });
            soundPlaying = true;
            clip.start();
            while (soundPlaying)
            {
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException exp)
                {
                    // TODO Auto-generated catch block
                    exp.printStackTrace();
                }
            }
        }
        catch (UnsupportedAudioFileException exp)
        {
            // TODO Auto-generated catch block
            exp.printStackTrace();
        }
        catch (IOException exp)
        {
            // TODO Auto-generated catch block
            exp.printStackTrace();
        }
        catch (LineUnavailableException exp)
        {
            // TODO Auto-generated catch block
            exp.printStackTrace();
        }
    }
    private static void createAndShowGUI()
    {
        JFrame frame = new TriggeringSoundTest();
        frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGUI());
    }
}