I tried to create a engine helpful for the Debugging of my code, but it seems it needs Debug on it's own... The mainfunction is a javax.swing-applikilation, from which I open other subclasses of the packages. I tried to put in a thread for the input in the Shell (I'm working with Eclipse), but the problem is that it doesn't work the second times it's opened. The first Time it does! I doesn't find any Ressource leaks or else. Somehow, it just outputs a empty line again and again. The break has to be with the opening and closing of the input-class, but the only thing I was able to find were tutorials how to use or to terminate threads (What I'm doing there, look at the end with the InterruptedException).
Weird is, that it does break the second time opened to this semi-errored state. usually, it would output a Exception the second opened time, but I coded it to do nothing instread.
Code:
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
public class Commander extends Thread {
/**
* #Author Ninto
*/
static String Input = "";
private static Logger log=null;
boolean running = true;
boolean scanning = true;
Commander(){
setDaemon(false);
}
public Commander(){}
#Override
public void run() {
running = true;
scanning = true;
input in = new input(); //Opens the Thread of the Subclass input
in.start();
while(running) {
TimeUnit.MILLISECONDS.sleep(25);
if(!Input.equals("")) {
switch(Input) {
case "something_else": break; //Do the debug there, like controlling the variables used by other classes
case "exit" : running = false; break; //Should close this Class & subclasses
case "stop" : System.exit(0); break; //Ends the program. Not to use!
}
}
Input = "";
scanning = true;
}
in.interrupt(); //Should break the Subclass - thread
TimeUnit.MILLISECONDS.sleep(100);
running = false;
}
class input extends Thread {
input() {setDaemon(true);} //To close the Thread with the exit of the Programm if still existing
private String Input = " ";
#Override
public void run() {
Scanner sc = new Scanner(System.in);
try {
while(true) {
if(isInterrupted()||!running) {
log.Log2("Spacecommander/Input","Stop Thread");
sc.close();
return;}
while(!scanning) {TimeUnit.MILLISECONDS.sleep(125);}
TimeUnit.MILLISECONDS.sleep(250);
try{this.Input = sc.nextLine();}
catch(NoSuchElementException e) {scanning = false;}
/*There does it break the Second time the Thread is used.
Another start of the Thread does the Same, only the first Time does it work.*/
Commander.Input = this.Input;
log.Log2("INPUT",Input);
this.Input = "";
scanning=false;}
}
catch(InterruptedException e) { //if this is called, it closes the Scanner and should exit the Programm.
sc.close();}
sc.close();
}
}
}
Think the problem is the various calls to sc.close() . Because the Scanner was created against System.in, this will be closed too.
Once the close() calls are removed, Eclipse will warn you about a resource leak - in your case it's right to ignore this, e.g. :
#SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
The other common technique in this situation is to keep the Scanner instance to be used by the next thread - e.g. in a shared static variable.
Related
I have taken a task upon myself to learn Java. My idea was to create a simple game with only the text console. The "AI" (timer) will periodically send a string and the player has to write a correct string in response, otherwise s/he loses a life.
My first question therefore is: Is there a simple way to combine timer and scanner? I need it to constantly "watch" the console line for strings.
After some time of searching and tries where I mostly struggled to scan the text while generating or generate strings while scanning I found following code but it has an issue at:
if ((name =in.nextLine(2000)) ==null)
If I rewrite the condition to, for example, compare to !="a" instead of null, the code just ignores the condition and always writes "Too slow!" no matter what. If it is =="a" it always says Hello, a. I completely don't understand why, it seems to ignore the logic.
So the second question would have been, why does it ignore the logic when it is different? And how do I fix it?
public class TimedScanner
{
public TimedScanner(InputStream input)
{
in = new Scanner(input);
}
private Scanner in;
private ExecutorService ex = Executors.newSingleThreadExecutor(new ThreadFactory()
{
#Override
public Thread newThread(Runnable r)
{
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
public static void main(String[] args) {
TimedScanner in = new TimedScanner(System.in);
int playerHealth = 5;
System.out.print("Enter your name: ");
try {
while (playerHealth > 0) {
String name = null;
if ((name = in.nextLine(3000)) ==null) {
System.out.println(name);
System.out.println("Too slow!");
playerHealth--;
} else {
System.out.println(name);
System.out.println("Hello, " + name);
}
}
} catch (InterruptedException | ExecutionException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
public String nextLine(int timeout) throws InterruptedException, ExecutionException
{
Future<String> result = ex.submit(new Worker());
try
{
return result.get(timeout, TimeUnit.MILLISECONDS);
}
catch (TimeoutException e)
{
return null;
}
}
private class Worker implements Callable<String>
{
#Override
public String call() throws Exception
{
return in.nextLine();
}
}
}
This is very barebones idea of what it should do. In the while I plan to put in a randomly picked string, that will be compared with the console input and wrong input = playerHealth--; correct input something else.
2) why does it ignore the logic when it is different? And how do I fix it?
You've stated:
If I rewrite the condition to, for example, compare to !="a" instead
of null, the code just ignores the condition and always writes "Too
slow!" no matter what.
In Java, NEVER (or almost never) compare two strings using == or !=. A String is an Object so comparing them using == means comparing them by address and not by value. So
if ((name = in.nextLine(3000)) != "a")
will always (or almost always) return true because any string returned from in#nextLine, be it "a" or something different, will be allocated on the heap at a different address than your hardcoded "a" string. The reason I'm saying "almost" is because Java uses a concept of String Pool: when creating a new reference to a literal it checks whether a string is already present in the pool in order to reuse it. But you should never rely on ==. Instead, use Object.Equals().
More discusion about Java String Pool here.
1) Is there a simple way to combine timer and scanner?
Well, console UI it's not really friendly with multi-threading when it comes to reading user input, but it can be done...
Your code has an issue: whenever the player loses a life, it has to press Enter twice - when it loses 2 life consecutively, it has to press Enter 3 times in order to receive a positive feedback from "AI". This is because you're not killing the preceding thread / cancelling the preceding task. So I suggest the following code:
private static Scanner in;
public String nextLine(int timeout) throws InterruptedException, ExecutionException
{
//keep a reference to the current worker
Worker worker = new Worker();
Future<String> result = ex.submit(worker);
try
{
return result.get(timeout, TimeUnit.MILLISECONDS);
}
catch (TimeoutException e)
{
//ask the worker thread to stop
worker.interrupt();
return null;
}
}
private class Worker implements Callable<String>
{
//you want the most up-to-date value of the flag, so 'volatile', though it's not really necessary
private volatile boolean interrupt;
#Override
public String call() throws Exception
{
//check whether there's something in the buffer;
while (System.in.available() == 0){
Thread.sleep(20);
//check for the interrupt flag
if(interrupt){
throw new InterruptedException();
}
}
//once this method is called there's no friendly way back - that's why we checked for nr of available bytes previously
return in.nextLine();
}
public void interrupt(){
this.interrupt = true;
}
}
I'm using scanner to read lines from file and replace some text in each line based on given pattern. This is done inside an API. My program is a multithreaded one. At once, more than one thread can call this particular API.
Following is the line scanner initialization line where the thread crashes:
public static void replaceInFile(Properties replacements, Path targetFile) {
...
Scanner in = new Scanner(targetFile, "UTF-8");
...
}
I'm sure no single file will be accessed by two threads at once. Can anyone hint me in the right direction as to what is happening?
UPDATE:
public Void call() throws Exception {
Iterator it = paths.iterator();
while(it.hasNext()){
try {
String filePath = it.next().toString();
//BuildUtil replacer = new BuildUtil();
BuildUtil.replaceInFile(replacements, Paths.get(filePath));
} catch(Exception e) {
e.printStackTrace();
}
}
This is the call() of the thread. Now I observe that it shows "Frame not available" even before stepping into the BuildUtils's replaceInFile method and sometimes after entering in there..I'm not able to figure out what's wrong.. The main thread is exiting I think but I see nothing strange happening here which should make it exit unexpectedly.
I found it. Actually it was my stupidity. I forgot to wait for the threads to exit and so the main thread exited even before threads could complete. Sorry for bothering!
So now I do :
for (int i = 0; i < threadsUsed; i++) {
pool.take().get();
}
for all the threads and shutdown the executor service in finally block
i must say i am a beginner in Java.
I use Eclipse. I want to accomplish the following scenario and couldn't find how to do it:
While a java program runs it outputs text to the console, i also want to be able to input text and process it without blocking the output by waiting for input.
Assume this:
-Thread 1 outputs a number to the console every second
-Thread 2 listens for input
(The code is a mockup)
//**Thread 1:**
int incrementBy = 0;
for (int i = 0; i < 1000; i++) {
i = i + incrementBy;
//Pause for 1 seconds
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print text
System.out.println(i);
}
//**Thread 2:**
String myIncrement = System.console().readLine();
(Now process the input and change the incrementBy var in Thread 1)
Right now in my program i am using 1 thread for input and another one for output. But i can easily change the design.
All i could find was something about server and client, i would like to keep my code in one place-package. And i currently don't know how to make a GUI with a text box for output and one for input.
Can you recommend something please?
SOLVED - it turns out I am VERY VERY new to JAVA.
It seems that java allows the user to input text while another thread outputs to the console.
This is the reason why i couldn't find anything in my searches for things like "java input and output to console asynchronous". I had a problem in my input code exactly where i was asking for input and because i knew from single threaded programs that the program halts until i enter the text and press enter i assumed that the error was thrown because the output thread was taking over the console and terminating the input thread.
Here is my code for those who search (Take it as a guide, might not work if compiled):
//Main app
public class textInpuOutputManager {
//here we create the two threads (objects that implement the runnable interface)
static TextInputObject ti;
static TextOutputObject to;
public static void main(String[] args) {
//we instantiate the objects
ti = new TextInputObject();
to = new TextOutputObject();
//we call the start method to start the threads for input and output
ti.start();
to.start();
}
}
//TextInputObject class
public class TextInputObject implements Runnable {
//Method that gets called when the object is instantiated
public TextInputObject() {
System.out.println("Created TextInputObject");
}
//create a thread object and check if it's not already created
static Thread thread;
//This method gets called from the main
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
//this method gets called by the thread.start(); from above
#
Override
public void run() {
System.out.println("Text input thread created and now it runs");
readTextFromConsole();
}
Scanner inputReader = new Scanner(System.in);
//check for input all the time - THIS WILL NOT HALT THE PROGRAM
public void readTextFromConsole() {
System.out.println("Enter something:");
String myinput = inputReader.nextLine();
System.out.println("You Entered: " + myinput);
readTextFromConsole();
}
}
//TextOutputObject
public class TextOutputObject implements Runnable {
//Method that gets called when the object is instantiated
public TextOutputObject() {
System.out.println("Created TextOutputObject");
}
static Thread thread;
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
#
Override
public void run() {
System.out.println("Text output thread created and now it runs");
//Make it output text every 4 seconds to test if you can input text while it's used for output
for (int i = 0; i < 100; i++) {
//Pause for 4 seconds
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print i to console
System.out.println(i);
}
}
}
Also BIG thank you for all of you who took the time to respond
I'm not sure exactly what it is you want to do, but if you're new and you don't know how to make guis, I would try a JOptionPane
String input = JOptionPane.showInputDialog("User input is returned as a string; use Integer.parseInt(input) to retrieve an integer from this method");
You could make two inner classes and implement Runnable in both of them.
import java.util.Scanner;
public class Test{
private Thread t1;
private Thread t2;
public static void main(String[] args){
new Test();
}
private class TOne implements Runnable{
public void run(){
int incrementBy = 0;
for (int i = 0; i < 1000; i++) {
i = i + incrementBy;
//Pause for 1 seconds
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print text
System.out.println(i);
}
}
}
private class TTwo implements Runnable{
public void run(){//Code for Thread 2
try{
Scanner scr = new Scanner(System.in);
System.out.println(scr.next());
}catch(Exception ex){
ex.printStackTrace();
}
}
}
public Test(){
t1 = new Thread(new TOne());
t1.run();
t2 = new Thread(new TTwo());
t2.run();
}
}
Not the most elegant way, and it doesn't work flawlessly. You'd have to tinker with the second Thread a little more. For information on how GUI etc. work you should check the Swing library. Googling it should work just fine.
Some important keywords for you wpuld be:
JFrame, JPanel, LayoutManager, JTextArea, JTextField, JButton, ActionListener, Inner Class
I am trying this program in java but I am not getting any output when I put everything in the run() method
Main.java:
public class Main {
static int line;
static boolean ret = true;
static BufferedReader br;
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
File f = new File("tere.dat");
// boolean ret = f.createNewFile() ;
br = new BufferedReader(new FileReader(f));
new Test(br.readLine());
new Test(br.readLine());
}
}
Test.java:
public class Test extends Thread {
private String input;
static int thread_count = 0;
public Test(String l)
{
input = l;
}
public void run()
{
System.out.println("Checking from other class : This was printed from file :>>");
System.out.println(input);
String upper = input.toUpperCase();
System.out.println("");
System.out.println("The String in all UpperCase :" + upper);
}
}
What I want to do is that I want to read lines from a file using two threads and then display whatever I get . I am new to Java
EDIT :
I was not using the start() method. Though even after using start() It reads only 2 lines from the file and stops. What could be the problem
?
You have to start() your Threads.
Also, i would suggest reading a good tutorial on Threads and concurrency in Java before proceeding, as it's a complex subject.
You need to start your thread with start() I suggest you not extend Thread but instead implement Runnable.
BTW: Unless you type impossibly fast, you won't see the difference in using threads. It will take about 0.1 milli-seconds to start the thread and finish it so unless you type much faster than that, it will make no difference.
You need to start threads:
(new Test(br.readLine())).start();
And also, you have to add some join to wait threads to finish because your main thread will finish execution before created threads.
You have to start them:
(new Test(br.readLine())).start();
(new Test(br.readLine())).start();
There are many threads on SO about interrupting reading the system.in but what I am looking for here is some kind of advice as to how to best code what I am trying to achieve.
I have a getlogin() method that needs to do the following: ask a user to input the desired login environnement details, if after 6 seconds user have not input a valid value ("live" or "test") then set userlogin variable to "test" and return it to the caller.
I have taken the following approach for the getlogin() implementation:
launch two threads which do the following:
thread1 creates a scanner object then calls scanner.nextline() and depending on user input set a variable userlogin. Interrupts thread2 before exiting thread1.
thread2 waits 6 seconds and if after that userlogin is still not set, then set a default value for userlogin. Interrupts thread1 before exiting thread2.
join thread2 to stop main Thread from returning userlogin as null
return userlogin
The problem I have with the approach is that scanner.nextline() does not interrupt when thread2 calls thread1.interrupt, which is why I do not join thread1 in step 2 as the main Thread would hang.
Is there a way to get thread1 to complete after thread2 interrupts it? Or else is this approach completely overkill and there is a much simpler way to achieve the contract?
The simplest solution is to expose the underlying stream in the "reading" thread and close that stream from the timeout thread. This should interrupt the reading and raise an exception. Handle this exception and you should be able to proceed with your logic. The only gotcha is that you won't be able to re-use the same stream again. Unfortunately there is no easy way to deal with interruption of blocking system calls.
EDIT:
Following a completely different line of reasoning; given that we can't close the input stream just to interrupt it, the only way I can think of is to use the "programmatic user input" facilities offered by the Robot class. Here is an example which works out for me:
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
public class ConsoleTest {
/**
* #param args
*/
public static void main(String[] args) {
new TimeoutThread().start();
new ReaderThread().start();
}
}
class ReaderThread extends Thread {
#Override
public void run() {
System.out.print("Please enter your name: ");
try(Scanner in = new Scanner(System.in)) {
String name = in.nextLine();
if(name.trim().isEmpty()) {
name = "TEST"; // default user name
}
System.out.println("Name entered = " + name);
}
}
}
class TimeoutThread extends Thread {
#Override
public void run() {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(5));
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
} catch(Exception e) {
e.printStackTrace();
}
}
}
The above code uses the logic that once that timeout has expired, we simulate a newline which will cause the "name" variable to be blank. Then we have a check which performs the necessary logic and sets the appropriate user name.
The gotcha about the above approach is that it:
Uses Robot class of AWT so might not play well with headless terminals (?)
Assumes that the focus window is the console window. If the focus is somewhere else, the ENTER key-press will be registered for that window as opposed to your application window.
Hope this helps you out. I'm really out of ideas now. :)
Why not just poll with System.in.available() if there are bytes to read? It is non-blocking: one can do the call to Scanner.nextLine(), which is blocking, when sure it works and does not block.
A FutureTask together with a lambda expression can also be used:
FutureTask<String> readNextLine = new FutureTask<String>(() -> {
return scanner.nextLine();
});
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(readNextLine);
try {
String token = readNextLine.get(5000, TimeUnit.MILLISECONDS);
...
} catch (TimeoutException e) {
// handle time out
}
Another version of geri's answer would be:
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<String> future = executor.submit(() -> {
try (Scanner in = new Scanner(System.in)) {
return in.nextLine();
}
});
try {
return future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e1) {
return ...;
}