I have a JButton that has an overridden actionPerformed(event) function as the following:
public void actionPerformed(ActionEvent event) {
try {
System.out.println("enters here");
Process p = Runtime.getRuntime().exec("python tetris.py");
} catch (Exception ex) {
System.err.println("error");
}
}
The problem with this code is that the Python subprocess begins while Java program is being executed and hence the console for the subprocess, which is meant to display as a full screen, is shrunk to a smaller size. So I decided to terminate the Java program before executing its subsequent process:
public void actionPerformed(ActionEvent event) {
try {
System.out.println("enters here");
Process p = Runtime.getRuntime().exec("python tetris.py");
System.exit(0);
} catch (Exception ex) {
System.err.println("error");
}
}
This presented a newer problem - although the subsequent process does appear as a full screen, because the Java program terminates before tetris.py gets fully executed, there is a delay between two processes, resulting the desktop content to blink for a second before tetris.py begins to run. At this point, I used waitFor():
public void actionPerformed(ActionEvent event) {
try {
System.out.println("enters here");
Process p = Runtime.getRuntime().exec("python tetris.py");
p.waitFor();
System.exit(0);
} catch (Exception ex) {
System.err.println("error");
}
}
As it turns out, waitFor() waits for the subprocess to terminate, which has the same problem from the first scenario in that the subprocess console is shrunk in size.
My goal is one of the following:
Either find a way for the subprocess to execute in full-screen mode (it does this on its own).
The parent process (Java program) can terminate if the subprocess executes correctly, but I need to get rid of the delay between the two processes.
I prefer the option of terminating the Java program because when I switch back from its subprocess to its own process with JPanel, the positions of all JButtons are messed up and hence requires a new execution anyways. Any inputs would be appreciated.
UPDATE:
What laune suggested didn't exactly work, as ProcessBuilder seemed to take effect as soon as the JButton is clicked, but I got an idea from there. Instead of checking the status of the subprocess, I just put the Java process to sleep for a certain duration (experimental value that lies somewhere between the points where Python program executing in a smaller window and Java program terminating too early to produce a prolonged delay).
public void actionPerformed(ActionEvent event) {
try {
ProcessBuilder pb = new ProcessBuilder("python", "tetris.py");
Process p = pb.start();
Thread.sleep(300); // less than 315 ~ 320 transition
System.exit(0);
} catch (Exception ex) {
System.err.println("error");
}
}
No matter what value I used, however, I could not make the transition happen flawlessly and the desktop content blinks briefly but the delay is shorter than before. To counteract this even further, I was thinking of setting the desktop black to make it seem nothing was being shown, but this obviously is not an idle approach - it depends on the performance of the processor and hence has a poor portability, not to mention that this does not provide a real solution to the problem. Any further pointers would be appreciated.
You might try
ProcessBuilder pb = new ProcessBuilder("python", "tetris.py" );
Process p = pb.start();
while( ! p.isAlive() ){
Thread.sleep( 10 );
}
System.exit(0);
You want fullscreen, give it fullscreen with setFullScreen. Try to avoid workarounds like the one you did. They almost always lead to other errors and workarounds which in the end make your app become unmaintainable.
I can't test it, but I hope it works for you.
Also, if you really have to do it your way, you shouldn't use System.exit(0) but instead Platform.exit().
Related
I am using JLine 2 to write a console application in Java. I need to make a password visible on the console for say 10 seconds, then erase it (on a GNU terminal).
I tried different things, amongst which :
putString(pass);
Thread.sleep(10*1000);
resetLine();
but no luck. Either the text does not show, or the text is not cleared.
Ok, I finally came up with the following (the class extends ConsoleReader):
public boolean showPassword(String pass, int millis) {
try {
resetPromptLine(" password>", pass, pass.length());
Thread.sleep(millis);
if (setCursorPosition(0) && killLine()) resetPromptLine(" password>", "", 0);
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
return false;
}
I use resetLine to show a custom prompt and the password; I also set the cursor to the end of the line. I wait a bit. I set the cursor to the end of the line and "kill the line". For the password to actually disappear, I have to call resetPromptLine once again.
To wait for an input from the user vs a given time, use readCharacter() instead of Thread.sleep().
I am developing a small game, (Java, LibGdx) where the player fills cloze-style functions with predefined lines of code. The game would then compile the code and run a small test suite to verify that the function does the stuff it is supposed to.
Compiling and running the code already works, but I am faced with the problem of detecting infinite loops. Consider the following function:
// should compute the sum of [1 .. n]
public int foo(int n) {
int i = 0;
while (n > 0) {
i += n;
// this is the place where the player inserts one of many predefined lines of code
// the right one would be: n--;
// but the player could also insert something silly like: i++;
}
return i;
}
Please note that the functions actually used may be more complex and in general it is not possible to make sure that there cannot be any infinite loops.
Currently I am running the small test suite (provided for every function) in a Thread using an ExecutorService, setting a timeout to abort waiting in case the thread is stuck. The problem with this is, that the threads stuck in an endless loop will run forever in the background, which of course will at some point have a considerable impact on game performance.
// TestClass is the compiled class containing the function above and the corresponding test suite
Callable<Boolean> task = new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
// call the test suite
return new TestClass().test();
}
};
Future<Boolean> future = executorService.submit(task);
try {
Boolean result = future.get(100, TimeUnit.MILLISECONDS);
System.out.println("result: " + (result == null ? "null" : result.toString()));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
future.cancel(true);
}
My question is now: How can I gracefully end the threads that accidentally spin inside an endless loop?
*EDIT To clarify why in this case, preventing infinite loops is not possible/feasable: The functions, their test suite and the lines to fill the gaps are loaded from disk. There will be hundrets of functions with at least two lines of code that could be inserted. The player can drag any line into any gap. The effort needed to make sure no combination of function gap/code line produces something that loops infinitely or even runs longer than the timeout grows exponentially with the number of functions. This quickly gets to the point where nobody has the time to check all of these combinations manually. Also, in general, determining, whether a function will finish in time is pretty much impossible because of the halting problem.
There is no such thing as "graceful termination" of a thread inside the same process. The terminated thread can leave inconsistent shared-memory state behind it.
You can either organize things so that each task is started in its own JVM, or make do with forceful termination using the deprecated Thread.stop() method.
Another option is inserting a check into the generated code, but this would require much more effort to implement properly.
The right way is to change the design and avoids never ending loops.
For the time being, inside your loop you could check if the thread is interrupted some way by: isInterrupted() or even isAlive().
And if it is you just exit.
It is not normal to have a never ending loop if it not wanted.
To solve the problem You can add a counter in the loop and if you reach a limit you can exit.
int counter = 0;
while (n > 0) {
counter++;
if (counter > THRESHOLD) {
break;
}
i += n;
// this is the place where the player inserts one of many predefined lines of code
// the right one would be: n--;
// but the player could also insert something silly like: i++;
}
I have a concurrency problem in Java that i'm to able to solve.
I want to set a timeout for a player to write an input and when it's turn is over I set a flag (player.myTurn) to false in another thread, which control the game logic, cause I want this thread to stay in the second while and set the timeout to infinity not to catching the SocketTimeoutException.
The problem is that after sending the command to the controllerServerSide on the last player input, this thread comes back to inputStream.readObject() before the variable myTurn is modified by the other Thread, so it set again the timeout, and this is a problem for the game.
How can I make this thread to wait until myTurn is changed (only over the last player input)?
ServerThread
public void run(){
while(!isStopped){
try {
while(!player.getMyTurn()){
socket.setSoTimeout(0);
}
socket.setSoTimeout(INPUT_TIMEOUT);
//ServerThread arrives here 'cause myTurn it isn't changed yet
String command = (String) inputStream.readObject();
socket.setSoTimeout(0);
controllerServerSide.receiveCommand(command);
}catch (IOException e) {}
GameThread
for(Player player : playerList){
if(!player.getConnectionState()){
player.setMyTurn(true);
//here it starts his turn
winner = turn.executeTurn(player);
//here it finish his turn
player.setMyTurn(false);
if(winner != null){
playerList.remove(winner);
break;
}
}
}
I'm sorry if this is a bad coding style, but I'm practically new to Java.
Thanks for your answers!
I'm designing a game in java called that's similar to the board game go. In the implementation there is also a mode called speed mode, where if a player doesn't take a turn within the time limit (5 seconds) the other player is to win. This mode can also be won normally be "capturing" the opposition piece. After either of these conditions is met , the game is to be ran again from the main menu. This works fine in normal mode and in speed mode when the win conditions are met by capturing. When it's won by time running out however it behaves very oddly, almost randomly prompting for input and printing.
The code for the time is as follows:
public Boolean speedMode(Player player, Player opponent) {
ExecutorService service = Executors.newSingleThreadExecutor();
try {
Runnable r = new Runnable() {
Boolean outOfRange;
public void run() {
do {
outOfRange = takeTurn(player);
} while (outOfRange == true);
}
};
Future<?> f = service.submit(r);
f.get(5, TimeUnit.SECONDS);
} catch (final InterruptedException e) {
System.out.println("The thread was interrupted during sleep, wait or join");
} catch (final TimeoutException e) {
player.setWon(false);
System.out.println("\n" + player.getName() +", you took too long... ");
return true;
} catch (final ExecutionException e) {
System.out.println("An exception from within the Runnable task");
}
return false;
}
When the TimeoutException happens the oppisite player wins while loop shown beow is exited and the correct congratulations are printed. The problem is when It starts the new game at the bottom line of code thats when the weird behaviour starts. Is there something I need to close perhaps in the timer method?It's almost like it's still running in the back ground.
else {
do {
timeOut = speedMode(second, first);
if(winCheck1(first) == true || timeOut == true){
break;
}
timeOut = speedMode(first, second);
} while (winCheck1(second) != true && timeOut != true);
if(player1.isWon() == true){
System.out.println("\n\nCongratulations " + player1.getName() + " you are the winner!\n\n");
}
else{
System.out.println("\n\nCongratulations " + player2.getName() + " you are the winner!\n\n");
}
}
//reload the menu
Game game = new Game();
}
Basically my question is; can anyone tell me why starting a new game does not work correctly after throwing a TimeoutException?
Is there something I need to close perhaps in the timer method?It's almost like it's still running in the back ground.
If you don't call shutdown on the executor the worker thread that the executor created will hang around. (This is independent of the scope in which you declared the executor.) If it is a non-daemon thread then it will keep the old JVM alive.
Also your task needs to be responsive to interruption. See the documentation for shutdownNow:
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
"Responding to interrupts" means checking Thread.currentThread().isInterrupted() to see if the thread has been canceled and then acting on it (finding a stopping place, doing cleanup, and exiting the run method), and restoring the interrupted flag (Thread.currentThread().interrupt()) if an InterruptedException or InterruptedIOException is caught.
I have an application which is quite resource intensive, it is using large images as input and some of the operations on these images can take a while. I am therefore looking to make some parts run in their own threads. To do this I have used the following code just to test out first:
Thread t1 = new Thread(new Runnable() {
public void run()
{
inputChooser.setFileFilter(filter);
inputChooser.addChoosableFileFilter(filter);
int img = inputChooser.showOpenDialog(this);
if (img == JFileChooser.APPROVE_OPTION) {
File file = inputChooser.getSelectedFile();
String filename = file.getName();
if (filename.contains("B10")) {
greenBand = 1;
}
if (filename.contains("B20")) {
greenBand = 2;
}
if (filename.contains("B30")) {
greenBand = 3;
}
if (filename.contains("B40")) {
greenBand = 4;
}
if (filename.contains("B50")) {
greenBand = 5;
}
if (filename.contains("B60")) {
greenBand = 6;
}
if (filename.contains("B70")) {
greenBand = 7;
}
try {
greenImage = ImageIO.read(file);
ImageIO.write(greenImage, "JPEG", new File("img2_tmp.jpeg"));
greenImage = ImageIO.read(new File("img2_tmp.jpeg"));
if (greenImage.getWidth() > 8000 | greenImage.getHeight() > 7000) {
greenImage = greenImage.getSubimage(1450, 1400, (greenImage.getWidth()-3200), (greenImage.getHeight()-3000));
}
update(greenImage, greenIcon, greenLabel);
loadingBar.setIndeterminate(false);
checkInput();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Input Image Error", "Input Error", WARNING_MESSAGE);
}
}
}});
t1.start();
When I run the application it freezes when this code is called. However, I have managed to get it to work once, I am not sure how but it ran perfectly (not the first time, it froze a few times first and then randomly worked one time). I haven't changed any of the code just some of the indents and such to get it to fit with the rest of the code and ever since it just continues to freeze. A button action press calls this method where the above code is, as soon as the buttons pressed it freezes.
Is there a reason as to why this is happening?
Thanks in advance
You are calling a non-thread-safe code (swing (is NOT thread safe)) from both threads (newly created and main thread) at the same time.
Make sure that you have decoupled the logic before creating new threads.
For this specific use case, I'd suggest that you use SwingWorkers in stead of threads, they are easy to use, and work well within the limitations of swing.
More about SwingWorkers at http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
Hope this helps.
Good luck.
It's difficult to say exactly, but I notice that the variable greenImage and greenBand are not declared anywhere. That makes me think they are global variables. If something else has access to them, it's possible that they're causing some manipulation that sends your code into an infinite loop or does other unexpected Bad Things.