I am developing an exam software in core java where I am conducting various tests for students.I am stuck at a piece of code where timer with countdown is set.
My problem is when I display minutes its working fine but when I try to display seconds with the minutes in mm:ss format its not working.
Code is:
// for below int ti=20,si=60;
// test is for 20 minutes
public void run() {
while (true) {
try {
Thread.currentThread().sleep(60000);
for (int i = 0; i <= 60; i++) {
etime.setText("Remaining Time:-" + ti + ":" + si);
System.out.println("Remaining Time:-" + ti + ":" + si);
Thread.currentThread().sleep(1000);
si--;
}
ti--;
if (ti == 0) {
close();
}
} catch (InterruptedException ex) {
Logger.getLogger(Exam.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Once si has counted down to 0, you need to reset it to 59.
Also, the i variable is completely unnecessary, and there is an off-by-one error in your loop.
Related
I have a program I made a while a back for a friend and I that functions as a timer and alarm. It plays a sound and shows an image when you start the timer, and plays another sound and image when the timer ends. It has been working fine (more or less), but my friend recently switched to Linux and has some much more interactive sound controllers that led to us discovering an issue with the program: each time a sound plays, it creates an entirely new input stream that doesn't get reused and won't go away until the program is closed entirely. Not only is this poor design on my part that I want to learn how to fix, but it also causes issues on my friend's end when he tries to use the timer multiple times without closing the program. I believe the fix is to make it so that all sound plays through one input stream (and if anyone knows more about the interactions of Java and Linux please correct me). I tried simply making the AudioInputStream a global variable and resetting it before each use, but this causes both the image and sound to quit working entirely, and I have no idea why. Below is the actionPerformed on button press from my current and defective code. Following that is the working but ineffective code.
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
boolean needNewThread = false;
if (imgWindow.getIcon() == null) {
needNewThread = true;
}
timeUpLabel.setText(" ");
BufferedImage buffImg = null;
try{
globalAudioIn.reset();
URL url = this.getClass().getResource("/EvilManiMani.wav");
globalAudioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(globalAudioIn);
clip.start();
buffImg = ImageIO.read(getClass().getResource("/images/cloudWait.png"));
imgWindow.setIcon(new ImageIcon(buffImg));
System.out.println(buffImg.toString());
} catch (Exception e){
System.out.println(e.getMessage());
}
Integer inputTime = Integer.parseInt(timeTextField.getText());
timerLabel.setText(inputTime + ":00");
if(needNewThread) {
t = new Timer(1000, new ActionListener (){
#Override
public void actionPerformed(ActionEvent ae){
String[] minsAndSeconds = timerLabel.getText().split(":");
boolean timesUp = false;
if(minsAndSeconds[0].startsWith("-")) {
timesUp = true;
String temp = minsAndSeconds[0].substring(1);
minsAndSeconds[0] = temp;
}
Integer minutes = Integer.parseInt(minsAndSeconds[0]);
Integer seconds = Integer.parseInt(minsAndSeconds[1]);
seconds += (minutes*60);
if(seconds > 0 && !timesUp){
minutes = --seconds/60;
seconds %= 60;
if(seconds >= 10) {
timerLabel.setText(minutes + ":" + seconds);
}else {
timerLabel.setText(minutes + ":0" + seconds);
}
}else if(seconds > 0 && timesUp) {
minutes = ++seconds/60;
seconds %= 60;
if(seconds >= 10) {
timerLabel.setText("-" + minutes + ":" + seconds);
}else {
timerLabel.setText("-" + minutes + ":0" + seconds);
}
}else if (seconds == 0){
timerLabel.setText("-0:01");
BufferedImage bufferedImg = null;
try {
globalAudioIn.reset();
URL url = this.getClass().getResource("/YouWin!.wav");
globalAudioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(globalAudioIn);
clip.start();
bufferedImg = ImageIO.read(getClass().getResource("/images/drinkyMattPog.png"));
imgWindow.setIcon(new ImageIcon(bufferedImg));
timeUpLabel.setText("Time's up");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
});
t.setRepeats(true);
t.start();
}
}
Working but ineffective:
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
boolean needNewThread = false;
if (imgWindow.getIcon() == null) {
needNewThread = true;
}
timeUpLabel.setText(" ");
BufferedImage buffImg = null;
try{
URL url = this.getClass().getResource("/EvilManiMani.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
buffImg = ImageIO.read(getClass().getResource("/images/cloudWait.png"));
imgWindow.setIcon(new ImageIcon(buffImg));
System.out.println(buffImg.toString());
} catch (Exception e){
System.out.println(e.getMessage());
}
Integer inputTime = Integer.parseInt(timeTextField.getText());
timerLabel.setText(inputTime + ":00");
if(needNewThread) {
t = new Timer(1000, new ActionListener (){
#Override
public void actionPerformed(ActionEvent ae){
String[] minsAndSeconds = timerLabel.getText().split(":");
boolean timesUp = false;
if(minsAndSeconds[0].startsWith("-")) {
timesUp = true;
String temp = minsAndSeconds[0].substring(1);
minsAndSeconds[0] = temp;
}
Integer minutes = Integer.parseInt(minsAndSeconds[0]);
Integer seconds = Integer.parseInt(minsAndSeconds[1]);
seconds += (minutes*60);
if(seconds > 0 && !timesUp){
minutes = --seconds/60;
seconds %= 60;
if(seconds >= 10) {
timerLabel.setText(minutes + ":" + seconds);
}else {
timerLabel.setText(minutes + ":0" + seconds);
}
}else if(seconds > 0 && timesUp) {
minutes = ++seconds/60;
seconds %= 60;
if(seconds >= 10) {
timerLabel.setText("-" + minutes + ":" + seconds);
}else {
timerLabel.setText("-" + minutes + ":0" + seconds);
}
}else if (seconds == 0){
timerLabel.setText("-0:01");
BufferedImage bufferedImg = null;
try {
URL url = this.getClass().getResource("/YouWin!.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
bufferedImg = ImageIO.read(getClass().getResource("/images/drinkyMattPog.png"));
imgWindow.setIcon(new ImageIcon(bufferedImg));
timeUpLabel.setText("Time's up");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
});
t.setRepeats(true);
t.start();
}
}
Thanks! Also, any and all constructive criticism on the code is welcome, whether it's relevant to the question or not.
Before you call clip.start(), add a listener in order to close the Clip and the AudioInputStream:
clip.open(audioIn);
clip.addLineListener(e -> {
if (e.getType().equals(LineEvent.Type.STOP)) {
clip.close();
try {
audioIn.close();
} catch (IOException e) {
System.err.println(e);
}
}
});
clip.start();
Since you have asked for constructive criticism: Never write catch (Exception). You don’t want to catch RuntimeException or its subclasses, because they usually indicate programmer mistakes which need to be exposed and fixed, not glossed over. In your case, you should use catch (LineUnavailableException | IOException e) instead.
Your catch block should not print e.getMessage(). Instead, use e.printStackTrace(), so if an exception occurs, you will know exactly what happened and where.
I am making a game in Java and wanted to implement a deltatime system. However I am not sure if I have implemented it correctly. Is the way I have done it correct, or should I change it.
My code looks like this:
long oldtime = System.nanoTime();
while (true) {
long newtime = System.nanoTime();
long deltatime = (newtime - oldtime) / 1000000;
System.out.println(deltatime);
oldtime = newtime;
// render code
try {
Thread.sleep(Math.max(0, 32 - deltatime));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
It looks like you want to measure how long the rendering took. Therefore, I suggest a cleaner approach by storing the starting time in a variable (start) and then calculating the difference to the current time after the rendering took place. This would allow you to measure sub-steps easily by just adding another comparison to the current time in between.
Always be careful with the units (ms, µs, ms) and make it obvious by naming the variable accordingly (e.g. deltaMs) or by using a comment. It's also a good idea to protect the reference by declaring it final.
Here is a simple example:
while (true) {
final long start = System.nanoTime(); // initial reference
// simulate render code
try { Thread.sleep(32); } catch (InterruptedException e) { e.printStackTrace(); }
final long deltaMs = (System.nanoTime() - start) / 1_000_000;
System.out.println("Render took " + deltaMs + "ms");
}
Here is a nested example:
while (true) {
final long start = System.nanoTime();
/* A */ try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); }
final long deltaMsPartA = (System.nanoTime() - start) / 1_000_000;
System.out.println("Render part A took " + deltaMsPartA + "ms");
final long startPartB = System.nanoTime();
/* B */ try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); }
final long deltaMsPartB = (System.nanoTime() - startPartB) / 1_000_000;
System.out.println("Render part B took " + deltaMsPartB + "ms");
final long deltaMs = (System.nanoTime() - start) / 1_000_000;
System.out.println("Overall render took " + deltaMs + "ms");
}
i'm new in Reactive programming and have a lot of questions.
I think it is not a lack of examples or documentation it is just my understanding is wrong.
I'm trying to emulate slow subscriber;
Here is the code example
Flux.create(sink -> {
int i = 0;
while (true) {
try {
System.out.println("Sleep for " + MILLIS);
Thread.sleep(MILLIS);
int it = i++;
System.out.println("Back to work, iterator " + it);
sink.next(it);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).subscribeOn(Schedulers.elastic())
.subscribe(x -> {
try {
System.out.println("Value: " + x + ", Thread: " + Thread.currentThread().toString());
Thread.sleep(MILLIS + 4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System out is
Sleep for 1000
Back to work, iterator 0
Value: 0, Thread: Thread[elastic-2,5,main]
Sleep for 1000
Back to work, iterator 1
Value: 1, Thread: Thread[elastic-2,5,main]
Sleep for 1000
Back to work, iterator 2
Value: 2, Thread: Thread[elastic-2,5,main]
I thought if subscriber is slow, i should see more threads due to Schedulers.elastic()
Also i tried to make publishOn() and it seems like i make it async, but still couldn't handle result in several threads.
Thanks for comments and answers.
If you want it to run in diferent threads you need to use .parallel() like this and the emit will be don in different thread
Flux.create(sink -> {
int i = 0;
while (true) {
try {
System.out.println("Sleep for " + MILLIS);
Thread.sleep(100);
int it = i++;
System.out.println("Back to work, iterator " + it);
sink.next("a");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
})
.parallel()
.runOn(Schedulers.elastic())
.subscribe(x -> {
try {
System.out.println("Value: " + x + ", Thread: " + Thread.currentThread().toString());
Thread.sleep(100 + 4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
})
;
}
I am trying to write a program where the participant communicates with the program (I/O) via a console. Trick is, the console is part of a GUI, because I need the program to run off of a executable jar file. I append text with a scrollable text field, like so
textArea.append(printChar);
I give the method a String to work with, and it uses a nested for loop to take it, char by char, and append each Char (using string.substring()).
My problem is that it freezes up the entire time its supposed to be printing, then just displays it all. I don't know why, because I tested it using System.out.print, and it worked exactly as I wanted. So something is different about appending and printing. Any ideas?
Also, I am using Thread.Sleep(100) for my wait time.
public void actionPerformed(ActionEvent evt) {
if (!preforming){
preforming = true;
String input = textField.getText(); //Text from Input
textArea.append(dungeon.name + ": " + input + newline); //Add "text" to bottom of console
String[] output = dungeon.action(input);
//print everything in array output, char by char, with 2-3 seconds after each
for (int i = 0; i < output.length; i++){
String printThis = output[i];
if (printThis.length() > 0){
for (int j = 0; j < printThis.length(); j++){
String printChar = printThis.substring(j, j+1);
textArea.append(printChar);
//System.out.print(printChar);
try{
Thread.sleep(5);
} catch (InterruptedException e) {
System.out.print("Error ");
}
/*try { //useless
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
}
}
textArea.append("" + newline);
}
//cleaning up input bar
textField.setText("");
textField.selectAll();
//Make sure the new text is visible, even if there
//was a selection in the text area.
textArea.setCaretPosition(textArea.getDocument().getLength());
preforming = false;
}
}
I've edited my answer as you are showing more of your codes. Since, there is an outer loop in your code, I just included it inside the run method of timer in this new edit. And also I don't have the code for the dungeon so I just temporarily replace it with constant values so the program can run in my test.
public void actionPerformed(ActionEvent evt) {
java.util.Timer timer = new java.util.Timer();
timer.schedule(new java.util.TimerTask() {
public void run() {
if (!preforming){
preforming = true;
String newline = "\n";
String dungeonName = "Star Light";
String input = textField.getText(); //Text from Input
textArea.append(dungeonName + ": " + input + newline); //Add "text" to bottom of console
String[] output = {
"Twinkle twinkle little star.",
"How I wonder what you are.",
"Up above the world so high."
};
//print everything in array output, char by char, with 2-3 seconds after each
for (int i = 0; i < output.length; i++){
String printThis = output[i];
if (printThis.length() > 0){
for (int j = 0; j < printThis.length(); j++){
String printChar = printThis.substring(j, j+1);
textArea.append(printChar);
//System.out.print(printChar);
try{
Thread.sleep(25);
} catch (InterruptedException e) {
System.out.print("Error ");
}
/*try { //useless
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
}
}
textArea.append("" + newline);
}
//cleaning up input bar
textField.setText("");
textField.selectAll();
//Make sure the new text is visible, even if there
//was a selection in the text area.
textArea.setCaretPosition(textArea.getDocument().getLength());
preforming = false;
}
}
}, 1);
}
I am looking for possible methods that can increase download speed and improve cpu, memory performance. Currently I am downloading file in segments and transferring data using java nio transferFrom function.
public void startDownload() {
threadService.execute(() -> {
double currentBytes = bytesDone.doubleValue();
//Download each segment independently.
for (int i = 0; i < segments; i++) {
if (intialState[i] != -1) {
threadService.execute(new Segment((i * sizeOfEachSegment)
+ intialState[i], (i + 1) * sizeOfEachSegment, i));
}
}
if (intialState[segments] != -1) {
threadService.execute(new Segment((segments * sizeOfEachSegment)
+ intialState[segments], sizeofFile, segments));
}
// Keep saving states of threads. And updating speed.
while (bytesDone.get() < sizeofFile) {
for (int i = 0; i < 1; i++) {
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
System.out.println("thread interupted while sleeping");
}
System.out.println(speed
= (int) ((bytesDone.doubleValue() - currentBytes) / 5120));
currentBytes = bytesDone.doubleValue();
avgSpeed[0] += speed;
avgSpeed[1]++;
}
states.saveState(stateArray, currentState);
}
// Download Complete.
try {
fileChannel.close();
file.close();
} catch (IOException ex) {
System.out.println("failed to close file");
}
currentState.set(2);
states.saveState(stateArray, currentState);
System.out.println("Alhamdullilah Done :)");
System.out.println("Average Speed : " + avgSpeed[0] / avgSpeed[1]);
});
}
public class Segment implements Runnable {
long start;
long end;
long delta;
int name;
public Segment(long start, long end, int name) {
this.start = start;
this.end = end;
this.name = name;
}
#Override
public void run() {
try {
HttpGet get = new HttpGet(uri);
// Range header for defining which segment of file we want to receive.
String byteRange = start + "-" + end;
get.setHeader("Range", "bytes=" + byteRange);
try (CloseableHttpResponse response = client.execute(get)) {
ReadableByteChannel inputChannel = Channels.newChannel(
response.getEntity().getContent());
while (start < end && currentState.get() == 1) {
delta = fileChannel.transferFrom(inputChannel, start, 8192);
start += delta;
bytesDone.addAndGet(delta);
stateArray.set(name, start);
}
stateArray.set(name, -1);
}
System.out.println("Thread done: " + name);
} catch (IOException ex) {
System.out.println("thread " + name + " failed to download");
}
}
}
This implementation gives 400+ kb/s but Internet Download Manager downloads same file at 500+ kb/s.
Are there any resources I can reuse(I noticed every connection initially takes time to reach its maximum speed so is there any way i can reuse the same thread to download the next portion of file as soon as it complete downloading previous)?