java, creating a loop while keyboardscanner dont receive an input - java

I´m trying to make a loop while keyboardscanner.nextline() is not received.I am stuck in here because i cant find a solution, i dont even know if it is possible... here is what im trying to do in code...
public String messagingread(String username) throws RemoteException {
Scanner keyboardScanner = new Scanner(System.in);
try {
while (keyboardScanner.nextLine().isEmpty) {
System.out.println("cant get in here");
//i can only get in here if the scann is only an enter(isempty), but i //want to get in here if i dont scan anything...i dont want isempty i want not //defined and i dont know how to do it ....
}
System.out.println("pls help")
}
}

this will execute a task in other thread and accept inputs till the input is empty. Also, be aware of closing Scanner
class Task implements Runnable {
private boolean shouldRun = true;
public void stop() {
this.shouldRun = false;
}
#Override
public void run() {
while (this.shouldRun) {
try {
Thread.sleep(1000);
System.out.println("Doing some work every 1 second ...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Task have been stopped, Bye!");
Thread.currentThread().interrupt();
}
}
public final class Example {
public static void main(String[] args) {
Scanner keyboardScanner = new Scanner(System.in);
try {
Task task = new Task();
// run the task on new Thread
Thread newThread = new Thread(task);
newThread.start();
/*
read lines while it is not empty:
(line = keyboardScanner.nextLine()) -> assign the input to line
!(line ...).isEmpty() -> checks that line is not empty
*/
System.out.println("Give me inputs");
String line;
while (!(line = keyboardScanner.nextLine()).isEmpty()) {
System.out.println("new line read :" + line);
}
// when you give an empty line the while will stop then we stop
// the task
task.stop();
} finally {
// after the piece of code inside the try statement have finished
keyboardScanner.close();
}
System.out.println("Empty line read. Bye!");
}
}

// retrieve not empty line
public static String messagingread(String username) {
try (Scanner scan = new Scanner(System.in)) {
while (true) {
String line = scan.nextLine();
// do it while line is empty
if (!line.isEmpty())
return line;
}
}
}

Related

Getting input from console in Java: Is it blocking or non-blocking?

I'm writing a Java program in which I read a line from Console, and do some processing around it. The processing might take 1-2 seconds (i.e. takes longer than the input rate), while I might keep receiving 50 lines per second.
Although there were some similar questions, they were addressing C/C++ and not Java. So my fundamental question is below:
While still processing an input/line, am I blocked from receiving new inputs? Or somehow they are queued in the system/JVM? Or better ask this way: Do I miss any lines while processing takes time? I don't want to miss any lines by any means.
Here is my code snippet:
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
//process line. Can take 1-2 seconds.
processInput(sc.nextLine());
}
sc.close();
UPDATE:
As suggested, I came up with making my code more thread-friendly, using Executors:
ExecutorService executorService = Executors.newFixedThreadPool(10);
while (sc.hasNext()) {
executorService.submit(new Runnable() {
public void run() {
processInput(sc.nextLine());
}
});
}
Just compare these two samples:
Frist, linear without multiple threads:
public class SampleClass {
public static void main(String[] args) {
SampleClass instance = new SampleClass();
instance.start();
}
private void start() {
Scanner sc = new Scanner(System.in);
String input;
while (!(input = sc.nextLine()).equals("exit")) {
processInput(input);
}
sc.close();
}
private void processInput(String input) {
try {
Thread.sleep(2000);
System.out.println("input: " + input);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Then, using a new thread for every input processing:
public class SampleClass {
public static void main(String[] args) {
SampleClass instance = new SampleClass();
instance.start();
}
private void start() {
Scanner sc = new Scanner(System.in);
String input;
while (!(input = sc.nextLine()).equals("exit")) {
processInput(input);
}
sc.close();
}
private void processInput(String input) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("input: " + input);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
Just try it. In both cases you don't miss input, but the difference is that without new threads the processing time adds up (of course) - it doesn't run parallel.
It is blocking, although the documentation could have been clearer: It keeps saying "A scanning operation may block waiting for input." While it could theoretically throw a NoSuchElementException instead of blocking, it seems to me that this is up to the implementation.

Stop Scanner from waiting for input

Goal
I'm currently building (to practice with java) a basic command line multiplayer turn-based game. In this game, each player has 5 seconds to make his move. When he makes his move (or when the timer ends) the other player starts his turn, etc etc.
The server sends a TimerEnded message every time the timer ends.
My current goal is to achieve flawless input reading that could be interrupted when a TimerEnded message arrives to the client.
Design
To achieve this I created a singleton called InputManager. This class handles all the input reading stuff. I created a method called ask which takes a callback as parameter. In this method I create a new thread and inside it I wait for an input with Scanner.hasNextInt.
This class has also the method closeInput which sends an Interrupt message to the thread described above.
Here's the current implementation of the class:
class InputManager{
private Thread thread;
private InputManager(){}
private static InputManager instance;
private static InputManager getInstance(){
if(instance == null){
instance = new InputManager();
}
return instance;
}
/**
* Ask user to type a number.
* #param onSelected When the user has made his choice, this callback will be executed
*/
public static void ask( Consumer<Integer> onSelected){
getInstance().thread = new Thread(() -> {
System.out.println("Type a number:");
Scanner sc = new Scanner(System.in);
int selection = -1;
while (selection == -1) {
if(Thread.currentThread().isInterrupted()){
return;
}
if(sc.hasNextInt()){
selection = sc.nextInt();
onSelected.accept(selection);
} else {
sc.next();
selection = -1;
}
}
});
getInstance().thread.start();
}
/**
* Reset input stream (?)
*/
public static void closeInput(){
try {
getInstance().thread.interrupt();
} catch(NullPointerException e){
// do nothing
}
}
}
Problem
This code is extremely unreliable. I'll show you what I mean in just a moment.
I made a toy class called Client and in the main I simulated the TimerEnd message income with a timer.
class Client {
/**
* Ask user to type a number and send it to the server
*/
void makeRequest(){
InputManager.closeInput();
InputManager.ask((selected) -> {
System.out.println("Sent message: " + selected);
});
}
public static void main(String[] args) {
Client client = new Client();
client.makeRequest();
// Simulate Server messages
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
System.out.println("Message received");
client.makeRequest();
}
}, 5000, 5000);
}
}
Here's how it works in action:
Type a number:
2
Sent message: 2
Message received
Type a number:
3
Sent message: 3
Message received
Type a number: // Here I don't type anything
Message received
Type a number:
Message received
Type a number:
Message received
Type a number: // Here I can send multiple messages on the same "turn"
1
Sent message: 1
2
Message received
Non-educated guess
Currently, I guess that Scanner remains waiting for input and so the if(isInterrupted) statement is not hit until an input is given. If so, how can I avoid this behaviour?
I understand that this question is extremely (and maybe unnecessarily) long, and since you read it let me thank you for taking your time.
Minimal, Complete and Verifiable code
package com.company;
import java.util.*;
import java.util.function.Consumer;
class InputManager{
private Thread thread;
private InputManager(){}
private static InputManager instance;
private static InputManager getInstance(){
if(instance == null){
instance = new InputManager();
}
return instance;
}
/**
* Ask user to type a number.
* #param onSelected When the user has made his choice, this callback will be executed
*/
public static void ask( Consumer<Integer> onSelected){
getInstance().thread = new Thread(() -> {
System.out.println("Type a number:");
Scanner sc = new Scanner(System.in);
int selection = -1;
while (selection == -1) {
if(Thread.currentThread().isInterrupted()){
return;
}
if(sc.hasNextInt()){
selection = sc.nextInt();
onSelected.accept(selection);
} else {
sc.next();
selection = -1;
}
}
});
getInstance().thread.start();
}
/**
* Reset input stream (?)
*/
public static void closeInput(){
try {
getInstance().thread.interrupt();
} catch(NullPointerException e){
// do nothing
}
}
}
class Client {
/**
* Ask user to type a number and send it to the server
*/
void makeRequest(){
InputManager.closeInput();
InputManager.ask((selected) -> {
System.out.println("Sent message: " + selected);
});
}
public static void main(String[] args) {
Client client = new Client();
client.makeRequest();
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
System.out.println("Message received: thread interrupted");
client.makeRequest();
}
}, 5000, 5000);
}
}
As I see it, you can use 3 types of threads:
The main thread switches between users, announces players to play, checks the winning condition and starts the timer at each turn.
A second thread reads constantly the user input. After reading user input, it notifies the main thread.
Finally a thread waits for 5 seconds and then notifies the main thread.
So I will use 2 Producers and 1 Consumer as follows:
A Producer which "produces" the scanned user input (it provides it to the Consumer).
A Producer which "produces" time out events (which notify the Consumer).
A Consumer which switches between players and starts the producers.
All this, so that you don't have to mess around with interrupting any running thread and there is no need to check if the Scanner is ready…
import java.util.Scanner;
public class Main {
private static final Scanner SCAN = new Scanner(System.in);
//This is the Scanner's input Producer:
private static class UserInputProducer extends Thread {
private final UserInputConsumer uInConsumer;
public UserInputProducer(final UserInputConsumer uInConsumer) {
this.uInConsumer = uInConsumer;
}
#Override
public void run() {
while (true) {
final int input = SCAN.nextInt();
SCAN.nextLine(); //Ignore the new line character.
uInConsumer.userInput(input); //Fire user input event (for the current user).
}
}
}
//This is the time out event Producer:
private static class TimeOutEventProducer {
private final UserInputConsumer uInConsumer;
private int validReportId = Integer.MIN_VALUE; //IDs starting from Integer.MIN_VALUE and
//going step by step to Integer.MAX_VALUE, which means about 4 billion resets can be done
//to this Producer before an unhandled overflow occurs.
public TimeOutEventProducer(final UserInputConsumer uInConsumer) {
this.uInConsumer = uInConsumer;
}
public synchronized void reset() {
new TimerOnce(this, ++validReportId).start(); //Start a new TimerOnce. Could be javax.swing.Timer with "setRepeats(false)".
}
/*sleepDone(...) is called by ALL TimerOnce objects... So we need an up-to-date id (the
reportId) to verify that the LAST one TimerOnce finished, rather than any other.*/
public synchronized void sleepDone(final int reportId) {
if (reportId == validReportId) //Only the last one timeout is valid...
uInConsumer.timedOut(); //Fire time out event (for the current user).
}
}
//This is just a "Timer" object which blocks for 5 seconds:
private static class TimerOnce extends Thread {
private final TimeOutEventProducer timeout;
private final int reportId;
public TimerOnce(final TimeOutEventProducer timeout,
final int reportId) {
this.timeout = timeout;
this.reportId = reportId;
}
#Override
public void run() {
try { Thread.sleep(5000); } catch (final InterruptedException ie) {} //Wait.
timeout.sleepDone(reportId); //Report that the time elapsed...
}
}
//This is the Consumer:
private static class UserInputConsumer {
private final String[] names;
private int input;
private boolean timedOut, hasInput;
public UserInputConsumer(final String[] names) {
this.names = names;
}
public synchronized int play() {
new UserInputProducer(this).start(); //Start scanning any user's input...
final TimeOutEventProducer timeout = new TimeOutEventProducer(this);
int i = -1;
do {
i = (i + 1) % names.length;
hasInput = false;
timedOut = false;
timeout.reset(); //Start the input wait timer...
System.out.print("User " + names[i] + " enter a number: "); //Clarify who's player is the turn.
while (!hasInput && !timedOut)
try { wait(); } catch (final InterruptedException ie) {} //Wait for user input or timeout.
//Interpret notification event (either user input, either timeout):
if (timedOut)
System.out.println("Sorry, out of time.");
else if (!hasInput)
throw new UnsupportedOperationException("Probably messed with the flags in the while-condition.");
}
while (input != 5); //Here you test the win/loss condition.
//Lets say, for example, the user that enters number '5' wins...
return i; //Return the winner's index.
}
public synchronized void timedOut() {
timedOut = true;
notify();
}
public synchronized void userInput(final int input) {
this.input = input;
hasInput = true;
notify();
}
}
public static void main(final String[] args) {
System.out.print("Enter number of players: ");
final int numPlayers = SCAN.nextInt();
SCAN.nextLine(); //Ignore the new line character.
final String[] names = new String[numPlayers];
for (int i=0; i<names.length; ++i) {
System.out.print("User " + (i+1) + " enter your name: ");
names[i] = SCAN.nextLine();
}
//Start the consumer (which in turn starts the producers) and start the main logic:
System.out.println(names[new UserInputConsumer(names).play()] + " wins!");
}
}
Note, the program never terminates because the Scanning is infinite. But you may alter this behavior by messing with the while (true) condition of the UserInputProducer.
Alright, I worked out a solution.
As I thought, the problem is that the while loop was (of course) blocking in Scanner.hasNext. To avoid blocking, I used a BufferedReader, which has this handy function, ready, which returns true whenever a new line is input in System.in.
Basically, I changed the InputManager.ask method to:
void ask(Consumer<Integer> onSelected){
getInstance().thread = new Thread(() -> {
System.out.println("Type a number:");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Scanner sc = new Scanner(reader);
int selection = -1;
try {
while (selection == -1) {
//While there is no input to be processed
while (!reader.ready()) {
//This lets throw an InterruptedException
Thread.sleep(100);
}
if (sc.hasNextInt()) {
selection = sc.nextInt();
onSelected.accept(selection);
} else {
sc.next();
selection = -1;
}
}
} catch (IOException | InterruptedException e) {
// do nothing: function ends
}
});
getInstance().thread.start();
}
I also added this (extremely ugly) piece of code to consume any input before resetting, to prevent any previous line to be detected as typed now (basically flush the last line).
(If anyone has a suggestion on how this can be done in a more elegant way, I'm more than happy to hear your thoughs)
public static void closeInput(){
try {
BufferedReader tmp = new BufferedReader(new InputStreamReader(System.in));
if(tmp.ready()){
tmp.readLine();
}
getInstance().thread.interrupt();
} catch(NullPointerException e){
// do nothing
} catch (IOException e) {
e.printStackTrace();
}
}

Scanner.nextInt() blocks

My code is working fine if it is the following way.
Scanner input = new Scanner(System.in);
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 3; i++)
{
Runnable worker = new ClassA();
executor.execute(worker);
}
Instead, I want to run continuously in while(true) loop and break the loop when user enters 1. I tried the following way but it is not working. it is not running continously but stopping (blocking) at this line int stop = input.nextInt(); Can anyone please tell me where the mistake is. Whether it is the correct way of doing or not if not please suggest an alternative. My code in Class A connects to jms queue and should continuously read messages from queue.
Scanner input = new Scanner(System.in);
ExecutorService executor = Executors.newFixedThreadPool(2);
while(true)
{
Runnable worker = new ClassA();
executor.execute(worker);
int stop = input.nextInt();
if(stop == 1) {
break;
}
}
EDIT: The following is the edited code. when scanner.nextInt() value is entered 1, finished = true. While(!finished) loop is break, code in it is not executing but still my Consumer class is running continuously.
public class ScannerProblem {
public static boolean finished = false;
static class Listener implements Runnable {
Scanner scanner = new Scanner(System.in);
#Override
public void run() {
while (true) {
System.out.println("scanning");
if (scanner.nextInt() == 1) {
System.out.println("scanning finished");
finished = true;
return;
} else {
System.out.println("scanned something strange");
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class Consumer implements Runnable {
javax.jms.Connection jmsConnection = null;
private static ProcessRequest processRequest = new ProcessRequest();
#Override
public void run() {
ActiveMQConnection con = new ActiveMQConnection();
jmsConnection = con.openTcpConnection();
try {
String json = null;
Session session = jmsConnection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("Upload_Queue");
MessageConsumer consumer = session.createConsumer(queue);
TextMessage message = (TextMessage) consumer.receive();
System.out.println("Message #" + ": " + message.getText());
json = message.getText();
processRequest.upload(json);
System.out.println("Thread ID: " + Thread.currentThread().getId());
if (jmsConnection != null) {
jmsConnection.close();
}
Thread.sleep(5000);
}
catch(JMSException e) {
e.printStackTrace();
}
catch(InterruptedException e){
e.printStackTrace();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(new Listener());
while (!finished) {
System.out.println("finished::"+finished);
pool.submit(new Consumer());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
int stop = input.nextInt() is a blocking call, so it execute ClassA runnable only once then wait for input.
You need to move input code to another thread so it's not blocking the executions of ClassA.
Maybe a better option would be to have only one execution of ClassA and have another while(true) loop inside it.

Process.getOutputStream.close() doesn't seem to work or something else?

I have this problem on my project for 2days now.. And I'm not sure what is the fault. My project includes 2 classes, the main and another one to be called via ProcessBuilder using ExecutorService.
Here are the codes.
main class:
public class DesktopApplication1View extends FrameView{
public Process process = null;
private executeCode execute = new executeCode();
public DesktopApplication1View(SingleFrameApplication app){
(.........)
jButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
console.setText("");
execute.start();
}
});
}
class executeCode implements Runnable{
private boolean executeStarted = false;
private ExecutorService executecode;
ReadStdout read;
WriteStdin write;
public executeCode(){
executecode = Executors.newSingleThreadExecutor();
read = new ReadStdout();
write = new WriteStdin();
}
public void start(){
if(executeStarted){
try {
// process.getInputStream().close();
process.getOutputStream().close();
process.destroy();
} catch (IOException ex) {}
}
console.append("start\n");//debugging purpose
executecode.execute(this);
}
public void run(){
console.append("Execute thread = " + Thread.currentThread().getName() + "\n");//debugging purpose
executeStarted = true;
try {
ProcessBuilder builder = new ProcessBuilder("java", "-cp", "Project.jar", "project/oddeven");
builder.redirectErrorStream(true);
process = builder.start();
read.startReadStdout();
write.startWriteStdin();
}
catch (IOException e1) {console.append("error io");}
// return;
}
}
class WriteStdin implements Runnable{
private String input = null;
private BufferedWriter writer = null;
private ExecutorService executeWrite = Executors.newSingleThreadExecutor();
public void startWriteStdin(){
writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
executeWrite.execute(this);
}
public void WriteStdin(){
console.addKeyListener(new java.awt.event.KeyAdapter() {
#Override
public void keyTyped(java.awt.event.KeyEvent e){
//save the last lines for console to variable input
if(e.getKeyChar() == '\n'){
try {
int line = console.getLineCount() -2;
int start = console.getLineStartOffset(line);
int end = console.getLineEndOffset(line);
input = console.getText(start, end - start);
writer.write(input);
writer.flush();
} catch (Exception e1) {}
}
}
});
}
#Override
public void run(){
console.append("Write thread = " + Thread.currentThread().getName() + "\n");//debugging purpose
if(input == null) this.WriteStdin();
}
}
class ReadStdout implements Runnable{
private ExecutorService executeRead = Executors.newSingleThreadExecutor();
private BufferedReader reader = null;
public void startReadStdout(){
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
executeRead.execute(this);
}
public void run() {
console.append("Read thread = " + String.valueOf(Thread.currentThread().getName()) + "\n");//debugging purpose
String line;
try {
while((line = reader.readLine())!=null)
console.append(line+"\n");
}catch (IOException e) {}
console.append("read done");//debugging purpose
}
}
oddeven class:
public class oddeven{
static double num = 0;
static int even = 0, odd = 0, zero = 0;
public static void main(String[]args) throws Exception{
odd();
}
public static void odd() throws Exception{
try{
BufferedReader dataIn = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter numbers\n(Input negative value to end)\n");
num = Double.parseDouble(dataIn.readLine());
while(num>=0){
if(num == 0)
zero++;
else if(num%2==0)
even++;
else
odd++;
num = Double.parseDouble(dataIn.readLine());
}
System.out.print("There are\n"+even+" even numbers\n"+odd+" odd numbers\n"+zero+" zero value");
} catch(NumberFormatException e){
System.out.print("Wrong input, enter again\n");
odd();
}
}
}
So. If I clicked the button once, output is:
start
Execute thread = pool-2-thread-1
Read thread = pool-3-thread-1
Write thread = pool-4-thread-1
Enter numbers
(Input negative value to end)
1
2
-1
There are
1 even numbers
1 odd numbers
0 zero value
read done
but if I close then start the application again then click the button twice without inputting anything on the first click, output will be:
start
Execute thread = pool-2-thread-1
read doneRead thread = pool-3-thread-1
Write thread = pool-4-thread-1
Enter numbers
(Input negative value to end)
1
2
-1
There are
2 even numbers
2 odd numbers
0 zero value
read done
As you can see, when I click the button twice without inputting on the first click, the outputstream is not closed, which I think is causing the oddeven class registers 2 input from the stream. But if you input on the first click then 2nd click didn't get any input and you clicked the button again, the stream won't register 2 input anymore, it will only register one.
This shouldn't happen, because firstly, the process is destroyed if you click the button and the bufferedwriter is instanced again. Or I can be wrong.
I hope you get my point. Thank you.

How do I ensure my program closes the socket whenever it closes normally or crashes?

Here is the code:
public static void main(String[] args) {
SocketWorker worker = null;
MyIOConsole mio = null;
try {
portNumber = 2012;
worker = new SocketWorker();
worker.assignPort(portNumber);
mio = new MyIOConsole();
mio.assignObject(worker);
Thread b = new Thread(mio);
b.start();
worker.run();
} catch (IOException e) {
e.printStackTrace();
}finally{
mio.applicationQuit();
}
}
The SocketWorker is simply a socket, listening the port 2012, and the MyIOConsole, will accept user command,
public class MyConsoleIO implements Runnable {
SocketWorker o;
static BufferedReader reader;
public void assignObject(Object o) {
reader = new BufferedReader(new InputStreamReader(System.in));
this.o = (SocketWorker) o;
}
#Override
public void run() {
String inputString = null;
System.out.println("Press 'q' to kill to program");
try {
inputString = reader.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (inputString.equalsIgnoreCase("q")) {
this.applicationQuit();
}
}
public void applicationQuit(){
this.o.stopWorking();
System.exit(0);
}
}
But when the Socket got the exception, even I catch them, the code
mio.applicationQuit();
keep run. I don't want that, I just want when the user close or crashed the application, the socket will close and quit. How can I solve it?
Add the following. The run method will be called as the JVM is exiting.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run(){
// cleanup code before JVM exit goes here.
}
});

Categories

Resources