Java asynchronous text input and output - java

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

Related

Java thread with Scanner works first but not second time?

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.

Synchronise ArrayList over two threads

I'm having a difficult time understanding how to synchronise an ArrayList over two threads. Basically, I want one thread appending objects to the list and the other one reading from that list at the same time.
Here is the class that deploys the threads:
public class Main {
public static ArrayList<Good> goodList = new ArrayList();
public static void main(String[] args) {
Thread thread1 = new Thread(new GoodCreator());
Thread thread2 = new Thread(new WeightCounter());
thread1.start();
thread2.start();
}
}
Then the two Runnable classes:
This one reads lines of two values from a text file and appends new objects.
public class GoodCreator implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
private static Scanner scan;
#Override
public void run() {
System.out.println("Thread 1 started");
int objCount = 0;
try {
scan = new Scanner(new File(System.getProperty("user.home") + "//Goods.txt"));
} catch (FileNotFoundException e) {
System.out.println("File not found!");
e.printStackTrace();
}
while(scan.hasNextLine()){
String line = scan.nextLine();
String[] words = line.split("\\s+");
synchronized(goodList){
goodList.add(new Good(Integer.parseInt(words[0]), Integer.parseInt(words[1])));
objCount++;
}
if(objCount % 200 == 0) System.out.println("created " + objCount + " objects");
}
}
}
This iterates over the arraylist and is supposed to sum up one of the fields.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
int weightSum = 0;
synchronized(goodList){
for(Good g : goodList){
weightSum += g.getWeight();
}
}
System.out.println(weightSum);
}
}
No matter the input, weightSum never gets incremented and stays 0
Thread 1 started
Thread 2 started
0
Any help is much appreciated
You are running two independently running threads. These thread can run in any order and if one stop e.g. to read from a file, the other thread doesn't assume it has to wait for it.
In short, your second thread completes before the first thread has added anything to the list.
There is no good fix as this is not a good example of why you would use multiple threads, however to get an outcome what you can do is this.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
throw AssertionError(ie);
}
int weightSum = 0;
synchronized(goodList){
for (Good g : goodList)
weightSum += g.getWeight();
}
System.out.println(weightSum);
}
}
}
This will print the sum 10 times, 0.1 seconds apart. Depending on how long your file takes to load you will be able to see the sum for what has loaded so far.
This is something called a producer-consumer task. You can do it with arraylist, but it's honestly just not the right way to approach this problem.
Luckily, Java provides us with some collections, the BlockingQueue collections, which are designed specifically for this reason;
//the collection with the stuff in it
static BlockingQueue<Object> items = new BlockingQueue<Object>();
//(there are a few different types of blocking queues, check javadocs.
//you would want Linked or Array blocking queue
//what happens on the reader thread
public void producer()
{
//read the data into the collection
for (all the data in the file)
{
//add the next item
items.put(/* next item from file or w/e */);
//stop if necessary
if (atEndOfFile) stillReadingData = false;
//etc
}
}
Now you need to read the data out of the queue - luckily this is easy enough;
//what happens on the other threads
public void consumer()
{
//keep this thread alive so long as there is data to process
//or so long as there might be more data to process
while (stillReadingData || !items.isEmpty())
{
//get the next item from the list
//while the list is empty, we basically sleep for "timeout" timeunits,
//then the while-loop would repeat, and so on
Object o = items.poll(long timeout, int units);
if (o != null) //process it
}
}
In this way, you can continuously add items to the queue with the producer thread, and the items will be processed as soon as a consumer thread is free (this approach scales well with lots of consumer threads). If you still need a collection for the items, then you should make a second collection and add them to that after they have been processed.
As a side note, you may still need to synchronize oprations which occur while processing the items. For example, you would need to synchronize increments on "weightSum" (or alternately use AtomicInteger).
Try this change in the WeightCounter class.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
int weightSum = 0;
while(goodList.isEmpty()) {
Thread.sleep(1000);
}
synchronized(goodList){
for(Good g : goodList){
weightSum += g.getWeight();
}
}
System.out.println(weightSum);
}
}
This change will cause the WeightCounter thread to wait for the other thread to finish populating the goodList with data before attempting to read from it.

Java reading number of lines in two files while using threads

I posted yesterday about this but my code was messy. What I'm looking to do is count the number of lines of two separate files and print the line number in a separate thread for each file.
This is what i have:
import java.io.File;
import java.util.Scanner;
public class fileReader implements Runnable
{
static int count = 0;
static int count1 = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest1.txt"));
Scanner file2 = new Scanner(new File("filetest2.txt"));
while (file1.hasNextLine())
{
count++;
file1.nextLine();
}
while (file2.hasNextLine())
{
count1++;
file2.nextLine();
}
}
catch(Exception e)
{
count = -1;
count1 = -1;
}
}
public static void main(String[] args)
{
(new Thread(new fileReader())).start();
System.out.println("File one has " + count + " lines");
System.out.println("File two has " + count1 + " lines");
}
}
The problem is that it does not work. Can someone point me in the right direction? Thanks.
You are on the right track using Runnable. You have a couple problems right now:
You currently create 1 fileReader with 1 thread for both files, but your intent is to have a separate thread for each.
You are trying to communicate between threads using some static variables, but you're not waiting for the worker thread to be done before printing the variables.
To solve your first problem, you need to create a new Runnable and a new thread for each file. (I'm going to rename your fileReader class to LineCounter to avoid confusion with the similarly named FileReader from the standard library).
class LineCounter implements Runnable {
private final File file;
public LineCounter(File file) {
this.file = file;
}
public void run() {
// Count lines in file.
}
}
Now you can create 2 separate LineCounter objects, one to count the lines in each file.
Thread thread1 = new Thread(new LineCounter(new File("filetest1.txt")));
Thread thread2 = new Thread(new LineCounter(new File("filetest2.txt")));
thread1.start();
thread2.start();
As for your second problem, your main thread must (the one that spawned off these two other threads) needs to wait for them to complete before reading the variables holding the number of lines in each file. You can instruct your main thread to wait for the another thread to complete by using join()
thread1.join();
thread2.join();
// Print your variables.
That being said, communicating between threads with static variables is dubious at best:
To really do this right, you'd have to either synchronize access to those variables, or else declare them as volatile.
When programming with threads, it's preferable to share as little state (variables) as possible with other threads.
Further, there exists the very convenient Executor framework which presents a nicer API for dealing with threads. One big win is that is allows you to easily return a value from a thread, which you could use to return the number of lines read.
The big changes are:
Your class implements Callable<Integer> instead of Runnable. The <Integer> part here means you want your thread to return an Integer (i.e. the number of lines in the file)
Instead of void run(), you define Integer call(), which returns the number of lines in the file.
Instead of creating Threads directly, you submit tasks to be done to an Executor.
Instead of join()ing threads together, simply get() the return value of a thread from a Future.
Converted to Executor style, the solution is something like
class LineCounter implements Callable<Integer> {
private final File file;
public LineCounter(File file) {
this.file = file;
}
public Integer call() {
// Count number of lines in file.
return numLines;
}
}
And in your main thread:
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> future1 = executor.submit(new LineCounter(new File("file1.txt")));
Future<Integer> future2 = executor.submit(new LineCounter(new File("file2.txt")));
Integer file1Lines = future1.get();
Integer file2Lines = future2.get();
You need to wait for the thread to finish its job.
You print your resault too early.
thr.join() blocks your program until thr finishes.
public static void main(String args[]) {
try {
Thread thr = new Thread(new fileReader());
thr.start();
thr.join();
System.out.println("File one has " + count + " lines");
System.out.println("File two has " + count1 + " lines");
} catch (InterruptedException ex) {
Logger.getLogger(fileReader.class.getName()).log(Level.SEVERE, null, ex);
}
}
public class fileReader1 implements Runnable
{
static int count = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest1.txt"));
............
............
............
}
}
public class fileReader2 implements Runnable
{
static int count = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest2.txt"));
............
............
............
}
}
Now you can start two threads and start reading the files simultaneously:
Thread t1=new Thread(new fileReader1());
Thread t2=new Thread(new fileReader2());
t1.start();
t2.start();

How do I adjust this for single/multithreaded?

I have a class that basically has two methods the first one takes a String (name of a file) and a thread:
public static void readFile(String s, Thread t){
Runnable read = new Runnable() {
public void run() {
//SOME CODE
}
t = new Thread(read);
t.start();
}
The second method is a main method that asks the user for input and then uses that input to set a few things (like if the number of threads is just one or if it is equal to the number of objects in a list).
public static void main(String[] args){
//SOME CODE
for(Object x: ListOfObjects){
//t1 is the same thread each time if one thread requested, otherwise t1 is a different thread each time
readFromFile(textFileString, t1);
//SOME CODE
}
If the user were to request 5 threads (for 5 items in a list), how could the above be modified for that? Currently, my main method has a loop (for the number of items in the list) and then the first method is called for each iteration in the loop. Is there a way to take the number of threads requested by the user, and initiate/start them in the first method all at once instead of one at a time and calling the method?
Implement the Runnable interface. I tried
this and it seems to work:
class StringThread implements Runnable
{
private String str;
private int num;
StringThread(String s, int n)
{
str = new String (s);
num =n;
}
public void run ( )
{
for (int i=1; i<=num; i++)
System.out.print ("THREAD NAMED: " + str+" I IS: " +
i + "\n");
}
}
//IN the main program:
StringThread t1 = new StringThread ("THR-1",100);
new Thread(t1). start ( );
StringThread t2 = new StringThread ("THR-2",200);
new Thread(t2). start ( );

Displaying busy status with thread in java

I'm writing a Java app which writes to excel sheet bunch of data, and it takes a while to do so.
I'd like to create something like writing out dots to screen like on Linux when you're installing something.
Is that possible in java?printing dots, while other thread actually does the writing to excel, then after its finished the one displaying dots also quits?
I'd like to print dots to console.
A variation to #John V. answer would be to use a ScheduledExecutorService:
// SETUP
Runnable notifier = new Runnable() {
public void run() {
System.out.print(".");
}
};
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// IN YOUR WORK THREAD
scheduler.scheduleAtFixedRate(notifier, 1, 1, TimeUnit.SECONDS);
// DO YOUR WORK
schedule.shutdownNow();
Modify the notifier object to suit your individual needs.
Its very possible. Use a newSingleThreadExecutor to print the dots while the other thread does the parsing. For example
ExecutorService e = Executors.newSingleThreadExecutor();
Future f = e.submit(new Runnable(){
public void run(){
while(!Thread.currentThread().isInterrupted()){
Thread.sleep(1000); //exclude try/catch for brevity
System.out.print(".");
}
}
});
//do excel work
f.cancel(true);
e.shutdownNow();
Yes, it is possible, you will want to have your working thread set a variable to indicate that it is working and when it is finished. Then create a thread by either extending the Thread class or implementing the Runnable interface. This thread should just infinitely loop and inside this loop it should do whatever printing you want it to do, and then check the variable to see if the work is done. When the variable value changes, break the loop and end the thread.
One note. Watch your processing speed. Use Thread.sleep() inside your loop if your processor usage goes way high. This thread should not be labour intensive. System.gc() is another popular way to make threads wait.
Not an elegant solution, but get's the job done. It prints 1, 2, 3, 1, 2... dots in a loop and terminates everything after 5 seconds.
public class Busy {
public Busy() {
Indicator i = new Indicator();
ExecutorService ex = Executors.newSingleThreadExecutor();
ex.submit(i);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i.finished = true;
ex.shutdown();
}
public static void main(String[] args) {
new Busy();
}
private class Indicator implements Runnable {
private static final int DOTS_NO = 3;
private volatile boolean finished = false;
#Override
public void run() {
for (int i = 0; !finished; i = (i + 1) % (DOTS_NO + 1)) {
for (int j = 0; j < i; j++) {
System.out.print('.');
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int j = 0; j < i; j++) {
System.out.print("\b \b");
}
}
}
}
}

Categories

Resources