Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm writing a videogame and I want to stop the music when a player loses or quits (to the main menu).
Here's my code:
public class Music{
private static Clip clip;
private static AudioInputStream stream;
private static void loadMusic(){
if(clip != null) return;
try {
AudioFormat format;
DataLine.Info info;
stream = AudioSystem.getAudioInputStream(Music.class.getResource("/resources/music/music.wav"));
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void playMusic(boolean loop){
loadMusic();
if(clip == null) return;
if(loop) clip.loop(Clip.LOOP_CONTINUOUSLY);
else clip.start();
}
public static void stopMusic(){
clip.stop();
clip.setMicrosecondPosition(0);
}
}
Whenever I call Music.stopMusic(), the game hangs for a few seconds then continues.
From what i gather form your description, you are pressing a stop button on your GUI and this calls Music.stopMusic(). The result is that the audio clip stops playing, but you are still waiting 3 seconds before you GUI becomes responsive.
This is because the call you are making in Music.stopMusic() makes native calls to I/O resources, and this should not be called in the EDT. You should look at running up a worker thread to do this:
Thread t = new Thread(new Runnable() {
public void run() {
Music.stop();
}
});
t.start();
Or look to using a SwingWorker.
Interestingly, though I am not sure which implementation of Clip is returned, but a quick look at MixerClip shows a call to a native library, and then perhaps the smoking gun in your predicament- a 3 second wait for a callback!
// stop the sample. this invalidates the sample voice id.
nStop(id);
// wait for the callback
synchronized(lock) {
if (id!=0) {
try {
//long time=System.currentTimeMillis();
lock.wait(3000);
//if (System.currentTimeMillis()-time > 2500) {
//System.out.println(" WAITING TIMED OUT!"); System.out.flush();
//id=0;
//}
} catch (InterruptedException e) { }
}
}
Related
I'm trying to add sound to a game I've been working on, and I'm having trouble getting the sounds to play more than once. I think I've worked out the cause, but I'm not sure how to solve it. I'm using an enumerator I found while searching for a Java sound tutorial.
The problem is that I'm calling the sound within a thread, in my update() method, and that each time I call the play() method of the sound, it starts the clip over. The first time it's called, the sound plays fine (I may get a bit of a freeze), but all attempts afterwards to play the sound fail. I don't get any exceptions or errors, the sound just doesn't play.
public enum Sounds {
RIFLE("rifle_fire.wav");
private Clip clip;
Sounds(String filename) {
openClip(filename);
}
public synchronized void openClip(String filename) {
try {
URL audioFile = Sounds.class.getResource("/resources/sounds/" + filename);
AudioInputStream audio = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audio.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(audio);
} catch (UnsupportedAudioFileException uae) {
System.out.println(uae);
} catch (IOException ioe) {
System.out.println(ioe);
} catch (LineUnavailableException lue) {
System.out.println(lue);
}
}
public synchronized void play() {
if(clip.isRunning()) clip.stop();
clip.setFramePosition(0);
clip.start();
}
public static void init() {
values();
}
}
That is the enumerator I use. It's called from the update() method of my main thread, which is updated every 20 ms. In the update method, I call it like this.
// If the left mouse button is held down, create a new projectile.
if(Globals.buttons[0] && !player.isOnCooldown()) {
createParticle(pAngle);
Sounds.RIFLE.play();
}
Someone suggested I need to close the line after using it, but the sound is only opened once... why would I need to close it? Anyone know what the problem is?
I'm currently developping a ftp client based on the package commons.net, in order to run tests to see the speed of the connection.
Basically my ftp test consists in connect to the server, logging onto it, and then start a cycle of download/upload as long as necessary, until the user decides to stop it via a button, then the current cycle will end and so will the test.
However, while running those tests, a situation requiering a timout mechanism has occured. the server was transmitting the file, and send the return code 226 (transfer complete) before it was indeed completed.
So my thread remains stuck, trying to empty the inputStream when it is not possible anymore.
My idea was to start a threaded timer with the downloading process, that will be reset each time a byte is transferred to my client.
When the timeout occurs, then an exception or so would be raised, and my client would react to it, abording the download.
I have read and try many solutions, among them:
- raising an exception from a thread -> the thread catches the exception and not the client;
- interrupt the client from the thread, so the client raises itself an interruptedException -> doesn't seem to work;
- using an executor with a timeout -> since I can't know the "normal" duration of a download, I can't give it to the executor when I start the task, moreover, the timer has to be reset when I receive data.
I read a lot about it on many forums, and didn't find any solution that seem to be adapted AND work in this case. If anyone has an idea of another way to do it?
This is the code of the action I am performing:
public double get(String fileName) {
[...]
org.apache.commons.net.io.Util.copyStream(stO,stD,client.getBufferSize(),
this.localSize,
new org.apache.commons.net.io.CopyStreamAdapter() {
public void bytesTransferred(long totalBytesTransferred,
int bytesTransferred,long streamSize) {
setProgressDL(totalBytesTransferred);
//reset the timer here
}
});
[...]
}
Here is some of the code of my test, launching my client:
public class TestFtp extends Thread {
[...]
public void run() {
System.out.println("Launching FTP test");
FtpClient client = new FtpClient(this.model, this, this.model.getFtpServer());
try {
//Attempting connection on the server
client.connect();
try {
// Attempting login
client.login(this.model.getUsername(), this.model.getPassword());
do {
client.changeDirectory("get");
// start timer
client.get(this.model.getDistantFileName());
// stop timer
client.changeToParentDirectory();
client.changeDirectory("put");
client.set(this.model.getDistantFileName(),
this.model.getNewFileName());
client.changeToParentDirectory();
try {
// Little pause between each test
Thread.sleep(500);
} catch (InterruptedException e) {}
// Continue test until the user stops it
} while (this.continuous);
// Once the test is over, logout
client.logout();
} catch (FTPLoginException e) {
// If login fails, the test ends
System.out.println("Unable to login to the server.");
}
} catch (FTPConnectException e) {
// If connection error, the test ends
System.out.println("Unable to connect to the server.");
}
}
Thank you by advance if anyone can help, and if you need further information on my actual code, I can put more of it in here.
If you do not want to throw unecessary Exceptions, you should use a boolean flag that controls the execution of the thread (or runnable):
public class TestFtp extends Thread {
[...]
boolean abort;
public void run() {
[...]
do{
[...]
} while (this.continuous && !abort);
if (abort){
// You might want to do something here
}else{
// The stuff you normally do
}
}
}
And then simply set the abort flag to false from outside.
This way you can better control how you thread will terminate, as thread.interrupt(); will have an undefined behavior.
Well, I'm sorry but I admit I haven't read all your code, but if you want to interrupt a running thread, do two things:
run the thread code inside a try/catch block like this:
Example:
public void run() {
try {
// code to run
} catch (InterruptedException ie) {
// thread interrupted, may want to do some clean up
// but must return as quickly as possible to avoid halting external code
}
}
Call the interrupt() method of the thread above externally when the need arises.
Example:
thread.interrupt();
This will tell the VM to throw the InterruptedException in your thread no matter what it's doing, giving you a chance to do some stuff.
I hope this is what you're looking for...
EDIT
Ok, a concrete example that works:
public class Driver {
private static int count = 0;
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
bigTask();
} catch (InterruptedException ie) {
System.out.println("Interrupted thread! Count is " + count);
}
}
});
t.start();
try {
Thread.sleep(1000);
System.out.println("Trying to interrupt thread");
t.interrupt();
} catch (InterruptedException e) {}
}
private static void bigTask() throws InterruptedException {
List<BigDecimal> bigs = new ArrayList<BigDecimal>();
for (int i = 0; i < 10000000; i++) {
bigs.add(BigDecimal.valueOf(i));
if (Thread.interrupted()) {
throw new InterruptedException();
}
count = i;
}
System.out.println("Ok, added ten million items, count is " + count);
}
}
I am not well-versed in Multi-Threading. I am trying to take screenshot repeatedly by one producer thread, which adds the BufferedImage object to ConcurrentLinkedQueue and a Consumer Thread will poll queue for BufferedImage object to saving them in file. I could consume them by repeated polling(while loop), but I don't know how to consume them using notify() and wait(). I have tried using wait() and notify in smaller programs, but couldn't implement it here.
I have the following code:
class StartPeriodicTask implements Runnable {
public synchronized void run() {
Robot robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit()
.getScreenSize());
BufferedImage image = robot.createScreenCapture(screenRect);
if(null!=queue.peek()){
try {
System.out.println("Empty queue, so waiting....");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
queue.add(image);
notify();
}
}
}
public class ImageConsumer implements Runnable {
#Override
public synchronized void run() {
while (true) {
BufferedImage bufferedImage = null;
if(null==queue.peek()){
try {
//Empty queue, so waiting....
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
bufferedImage = queue.poll();
notify();
}
File imageFile = getFile();
if (!imageFile.getParentFile().exists()) {
imageFile.getParentFile().mkdirs();
}
try {
ImageIO.write(bufferedImage, extension, imageFile);
//Image saved
catch (IOException e) {
tracer.severe("IOException occurred. Image is not saved to file!");
}
}
}
Previously I had a repeated polling to check for existence of BufferedImage Object. Now I have changed run method as synchronised and tried to implement wait() and notify(). Am I doing correct? Please help. Thanks.
You are using the wrong Queue for the job. The ConcurrentLinkedQueue is a non-blocking Queue which means that there is no producer consumer semantics. If you are just doing one reader and one writer take a look at SynchronousQueue
Simply put your code can be re-written as such
BlockingQueue<?> queue = new SynchrnousQueue<?>();
class StartPeriodicTask implements Runnable {
public void run() {
Robot robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit()
.getScreenSize());
BufferedImage image = robot.createScreenCapture(screenRect);
queue.offer(image); //1
}
public class ImageConsumer implements Runnable {
#Override
public void run() {
while (true) {
BufferedImage bufferedImage = queue.poll(); //2
File imageFile = getFile();
if (!imageFile.getParentFile().exists()) {
imageFile.getParentFile().mkdirs();
}
try {
ImageIO.write(bufferedImage, extension, imageFile);
//Image saved
catch (IOException e) {
tracer.severe("IOException occurred. Image is not saved to file!");
}
}
That's really it.
Let me explain. At line //1 the producing thread will 'place' the image on the queue. I quotes place because a SynchrnousQueue has no depth. What actually happens is the thread tells the queue "If there are any threads asking for an element from this queue then give it the that thread and let me continue. If not I'll wait until another thread is ready"
Line //2 is similar to 1 where the consuming thread just waits until a thread is offering. This works great with a single-reader single-writer
The first problem is the unnecessary wait that you have in your producer:
if(null!=queue.peek()){ // You are the producer, you don't care if the queue is empty
try {
System.out.println("Empty queue, so waiting....");
wait(); // This puts you to bed, your waiting and so is your consumer
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
queue.add(image);
notify();
}
This is all you should need:
queue.add(image);
notify();
The next issue is the unnecessary notify in your consumer. It yields control of its processing at that point, which I believe you intended as a way to get your producer going, but of course your code never gets to that point. So this:
}else{
bufferedImage = queue.poll();
notify();
}
File imageFile = getFile();
if (!imageFile.getParentFile().exists()) {
imageFile.getParentFile().mkdirs();
}
try {
ImageIO.write(bufferedImage, extension, imageFile);
//Image saved
catch (IOException e) {
tracer.severe("IOException occurred. Image is not saved to file!");
}
}
Should look more like this:
}else{
bufferedImage = queue.poll();
File imageFile = getFile();
if (!imageFile.getParentFile().exists()) {
imageFile.getParentFile().mkdirs();
}
try {
ImageIO.write(bufferedImage, extension, imageFile);
//Image saved
catch (IOException e) {
tracer.severe("IOException occurred. Image is not saved to file!");
}
}
Once the java.util.concurrent library came into the JDK1.5, the need to write your own wait/notify logic went right out the door. In 2012, if you are doing your own wait/notify, you are working too hard and should strongly consider the tried and true java.util.concurrent equivalents.
That being said, I believe polling is the idea behind the built in java.util.concurrent.ConcurrentLinkedQueue. In other words, the consumers sit in their own Thread and .poll() items from the ConcurrentLinkedQue as long as it is !isEmpty(). Most implementations that I've seen throw some sort of a one second sleep between tests of the !isEmpty(), but I don't think that is actually necessary. Also, pay note to the Vint guy's comment on my answer, .poll() may return null. Consider alternative implementations of java.util.AbstractQueue that may have blocking behavior closer to what you are looking for.
This guy's got a simple example: http://www.informit.com/articles/article.aspx?p=1339471&seqNum=4
Finally, get the Goetz book "Java Concurrency In Practice" and read it. I'm almost sure it has a recipe for what to use to replace your own home-grown wait/notifys.
ImageThread it = new ImageThread(this.imageURL,this);
Thread t = new Thread(it);
t.start();
I'm new to threads and had to implement the above in my field that loads an image, because it slowed down the UI thread.
Whether my threads are downloading an image or some json content, they appear to still be downloading even though the user has pushed a new mainscreen onto the uiapplication. This continuous loading could be a problem if a user enters a screen and then accesses another in quick succession. As a result, the last screen they are on only finishes its thread when the others are done.
What am I supposed to do with my threads that would be deemed responsible? I don't want my app to be bogged down by a queue of threads. How do I, say, cancel downloads on screen change?
I'm posting this question in Java since I think the process is the same.
You can force your threads to close by keeping a public close() method inside your class that extends Thread:
private class MyConnectionThread extends Thread {
/** determines whether the thread is runnuing or not. */
private boolean alive = false;
private HttpConnection hconn = null; // or whatever connection method you want to use ( SocketConnection etc.)
private InputStream inputStream = null; // or DataInputStream etc...
public MyConnectionThread() {
alive = false;
// ...
// ...
}
public void run() {
alive = true;
try {
String connection_parameter = ";deviceside=false"; // [For BlackBerry: ] this parameter is for connection using MDS, need to add different parameters for different connection methods.
hconn = (HttpConnection) Connector.open("http://your_url.com"+connection_parameter);
int response = hconn.getResponseCode();
if (response == HttpConnection.HTTP_OK) {
inputStream = hconn.openInputStream();
// process the result here by reading the inputStream ...
// ...
// ...
}
inputStream.close();
hconn.close();
}catch(Exception excp) {
// Handle Exceptions here...
}catch (Throwable e) {
// Exception in reading inputStream
}finally{
alive = false;
this.interrupt();
}
}
/**
* Forces the connection to close anytime.
*/
public void closeConnection() {
alive = false;
try {
if (inputStream != null) {
inputStream.close();
}
inputStream = null;
if (hconn != null) {
hconn.close();
}
hconn = null;
this.interrupt();
} catch (Exception excp) {
// Handle Exception here...
System.out.println("Exception in closing HttpConnection: " + excp.toString());
}
}
}
Now whenever you navigate to another screen you just need to call the MyConnectionThread.closeConnection() method to force-close this Thread.
See Also:
how-to-abort-a-thread-in-a-fast-and-clean-way-in-java
How can we kill the running thread in java?
How to Stop a Thread or a Task
Hope these will be helpful for you.
As #Rupak suggested you make method (using isDisplayed() for example):
boolean isScreenOnTop()
And pass it to the Thread (better over interface StopCondition.shouldStop()). And modify you downloading algorithm to next:
while(moreDataAvailable() && !topCondition.shouldStop()) {
loadNextDataChunk();
}
if (!topCondition.shouldStop()) {
notifyDataDownloaded();
}
I am trying to play a sound in Java.
So far it is going well, thank you, but I have a problem understanding how does this work.
I wrote a function that does the playback:
private static void PlaySound(String path) {
try {
final File SoundFile = new File(path);
AudioInputStream Sound = AudioSystem.getAudioInputStream(SoundFile);
DataLine.Info info = new DataLine.Info(Clip.class, Sound.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(Sound);
clip.addLineListener(new LineListener() {
public void update (LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
event.getLine().close();
System.out.printf("Playback ended!");
System.exit(0);
}
}
});
System.out.printf("This sound is %f seconds long.", (clip.getMicrosecondLength() / 1000.0d));
clip.start();
} catch (Exception e) {
ErrorHandler(e);
}
}
Now this function works almost fine: when the sound has ended, it calls the event.getLine().close(); function, but it is stuck in an "infinite loop" (not sure if it is) and nothing after that statement gets executed, and the program runs until I kill it manually.
If I change the line
if (event.getType() == LineEvent.Type.STOP) {
to
if (event.getType() == LineEvent.Type.CLOSE) {
then the sound plays, and the program exits correctly, but still none of the statement after the event.getLine().close(); are executed.
The question is: is this the intended behavior of event.getLine().close(), or I am doing something wrong?
Solution:
The LineListener is actually based on an outdated fact, that Java Sound has a bug in it, and we need to exit explicitly from the vm. Without the listener, the code just works fine.
See if it's raising an exception:
public void update (LineEvent event) {
if (event.getType().equals(LineEvent.Type.STOP)) {
try {
event.getLine().close();
} catch (Throwable t) {
t.printStackTrace();
}
System.out.printf("Playback ended!");
}
}