Java problems w/ printing in new thread - java

I have my code setup so that when a long process is happening on the main thread of my Java program, another thread is opened to show a loading animation on the console, but this isn't working and the loading animation just prints all at once after the thread is closed. BUT it works if I use println() instead of print(), then the dots are printed every 200 milliseconds while the thread is running as expected but I need them to be printed on the same line. See code below.
Main thread:
Thread animate = new Thread(new ConsoleAnimator(".",200));
animate.start();
//do stuff for a few seconds
animate.interrupt();
Secondary thread:
public class ConsoleAnimator extends Thread{
public int animateInterval;
public String animateString;
public ConsoleAnimator(String toAnimate, int interval){
this.animateInterval = interval;
this.animateString = toAnimate;
this.setPriority(Thread.MAX_PRIORITY);
}
public void run(){
try{
while(true){
Thread.sleep(animateInterval);
refresh();
}
} catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
void refresh(){
System.out.print(animateString);
System.out.flush();
}
public void interrupt(){
System.out.println();
super.interrupt();
}
}
Would appreciate any help, thanks

The System.out is line buffered. There needs to be a newline before it's outputted to console.
If you need it to remain on the same line you could choose to use Use System.err that should work for your purposes.
If you rewired stderr to another output like file you could write your own console output.
See it in action: https://ideone.com/mlyPdx
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream(FileDescriptor.out), "ASCII"), 512);
out.write("test");
out.flush();
out.write(" > ");
out.flush();
out.write("string");
out.flush();
This is the code that runs on my sytem, windows 7 and cmd
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
public class Test
{
public static void main (String[] args) throws java.lang.Exception
{
Thread animate = new Thread(new ConsoleAnimator(".",200));
animate.start();
for(int c =0; c < 20; c++) {
Thread.sleep(1000);
}
animate.interrupt();
}
}
class ConsoleAnimator extends Thread{
public int animateInterval;
public String animateString;
protected BufferedWriter out;
public ConsoleAnimator(String toAnimate, int interval) throws IOException {
this.animateInterval = interval;
this.animateString = toAnimate;
this.setPriority(Thread.MAX_PRIORITY);
this.out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(FileDescriptor.out), "ASCII"), 512);
}
public void run(){
try{
while(true){
Thread.sleep(animateInterval);
refresh();
}
} catch(InterruptedException e){
Thread.currentThread().interrupt();
}
catch( Exception e) {
Thread.currentThread().interrupt();
}
}
void refresh() {
try {
this.out.write(animateString);
this.out.flush();
}
catch(IOException ex) {
}
}
public void interrupt() {
try {
this.out.write(System.lineSeparator());
this.out.flush();
}
catch(IOException ex) {
}
super.interrupt();
}
}

Why not use some libs such as progressbar, java-progressbar?
If you want to know why your code does not work, you can look up the code of these libs.

Related

Jline input disrupted by System out

I'm having some trouble with Jline and not quite understanding how to work it properly, everything seems to work from the examples but when i attempt to move it into my console application things go weird.
I've come across two issues:
When you write input into the console while something else is logging a message via System out, the written input gets broken. (View: https://i.imgur.com/ZAJDjTI.png)
I attempted to sync the commands to the main thread since the reader thread will be blocking, but this time you'll find that this causes the output text to take over the commands input space.
((Green text is the input, white is output)View: https://i.imgur.com/CdKiIYy.png)
The output i expected was for input coming from the bottom of the console to be unaffected by the output of the console, leaving a smooth input text layer at the bottom. (View: https://i.imgur.com/HfH5l8U.png?1)
Here's an example class i wrote to demonstrate the two problems I'm having:
import jline.console.ConsoleReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.ReentrantLock;
public class Example {
private ConsoleReader consoleReader;
private LinkedList<Runnable> syncQueue = new LinkedList<>();
private ReentrantLock lock = new ReentrantLock();
public Example() {
try {
this.consoleReader = new ConsoleReader();
this.consoleReader.setExpandEvents(false);
} catch (IOException e) {
e.printStackTrace();
}
//If you enable this, Jline seems to be disrupted by the System out.
// startStopwatch();
setupJline();
//Ticker, its ugly i know
while (true) {
lock.lock();
try {
while (syncQueue.size() > 0) {
Runnable runnable = syncQueue.poll();
try {
runnable.run();
} catch (Exception e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void setupJline() {
new Thread("Console Thread") {
#Override
public void run() {
while (true) {
try {
String line = consoleReader.readLine(">");
if (line != null && line.trim().length() > 0) {
//Lets pass this on as an instruction to our program
//Sync seems okay, output wise
handleInstructionSynced(line);
//async seems to mess things up though, comment the handleInstructionSynced method and
//uncomment the Async one to see what i mean.
//handleInstructionAsync(line);
}
consoleReader.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
}
//Just a dummy example instruction handler
private void handleInstructionAsync(String input) {
System.out.println("You've input \"" + input + "\" as your instruction.");
}
private void handleInstructionSynced(String input) {
runSync(() -> System.out.println("You've input \"" + input + "\" as your instruction."));
}
private void runSync(Runnable runnable) {
lock.lock();
try {
syncQueue.add(runnable);
} finally {
lock.unlock();
}
}
private void startStopwatch() {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
int time = 0;
#Override
public void run() {
System.out.println(time + " seconds counted");
time++;
}
};
timer.scheduleAtFixedRate(timerTask, 0, 1000);
}
public static void main(String[] args) {
new Example();
}
}
Any solutions?

Why doesn't my Java program write String into file?

I have two Threads and each Thread should write its name and an increasing number into a file - but it doesn't work.
If i use the System.out.println() method the threads are working perfectly only the writing into the file does fail. Any idea why?
This is how my Threads look like:
package ThreadTest;
import java.io.*;
public class Thread1 implements Runnable {
public void run() {
int x = 0;
while (true) {
try {
BufferedWriter p1 = new BufferedWriter(new FileWriter("C:\\Users\\User\\Desktop\\a1.txt"));
x++;
p1.write("Thread11: " + x);
Thread.sleep(500);
p1.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
The main class looks like this:
package ThreadTest;
public class ThreadTestTest {
public static void main(String args[]) {
try {
Thread1 t11 = new Thread1();
Thread t1 = new Thread(t11);
Thread2 t22 = new Thread2();
Thread t2 = new Thread(t22);
t2.start();
t1.start();
t1. join();
t2. join();
} catch (Exception e) {
e.getMessage();
}
}
}
After you close the file, you immedately open it again and thereby truncate it to zero length.
As Henry already pointed out, you essentially need to make your BufferedWriter shared between the threads so you don't constantly overwrite the file again.
The following will do:
public class ThreadTest {
public static void main(String[] args) {
class ThreadSafeBufferedWriter extends BufferedWriter {
public ThreadSafeBufferedWriter(Writer out) {
super(out);
}
#Override
public synchronized void write(String str) throws IOException {
super.write(str);
}
}
try (BufferedWriter p1 = new ThreadSafeBufferedWriter(new FileWriter("/tmp/out.txt"))) {
Thread t1 = new Thread(new Payload("Thread1", p1));
Thread t2 = new Thread(new Payload("Thread2", p1));
t2.start();
t1.start();
t2.join();
t1.join();
}
catch (Exception e) {
// do something smart
}
}
}
The actual payload comes in a Runnable which goes here:
class Payload implements Runnable {
private String name;
private Writer p1;
public Payload(String _name, Writer _p1) {
this.name = _name;
this.p1 = _p1;
}
#Override
public void run() {
int x = 0;
while (x < 10) { // you have to make sure these threads actually die at some point
try {
x++;
this.p1.write(this.name + ": " + x + "\n");
Thread.sleep(500);
} catch (Exception e) {
// do something smart
}
}
}
}
Thanks guys :)!
I just added a true to the file location:
PrintWriter p2 = new PrintWriter(new FileWriter("C:\\Users\\User\\Desktop\\a1.txt",true));
And now java appends the text instead of overwriting the old one.

Console output to file using multithreading

Is there a way to save the whole console output to a file when multithreading? I'm working with 5 threads. I had this idea that i can put a printstream in the run-method.
example:
public void run() {
try{
PrintStream out = new PrintStream(file);
stopExecute stop = new stopExecute();
Thread t = new Thread(stop);
Scanner in = new Scanner(System.in);
t.start();
while (!in.hasNextLine())
{
classThatUsingMultipleThrads();
System.out.println("Finished");
anotherClassThatUsingThreads();
System.out.println("Finished");
}
System.out.prinln("User stopped the execution");
stop.keepRunning = false;
System.setOut(out);
}
catch(IOException e){System.out.println(e);}
Problem here is that it's only saving the output "User stoped the execution" and everything in the whileloop are not saved. Or the outputstream from other classes.
I've tried to put the
System.setOut(out);
in the while-loop, but didn't help.
Edit: Spell correction
try {
System.setOut(new PrintStream(new File("output-file.txt")));
}
catch (Exception e) {
e.printStackTrace();
}
thanks to: System.out to a file in java
You should probably look into using a logging library such as Log4J. However you could also use something like a TeeOutputStream. This type of output stream writes to 2 other streams when called. A few libraries have great implementations but you can also write one yourself. I whipped this one up real quick.
You could set the output stream for your entire program in your main method to use this TeePrintStream, then all calls to System.out.* will write data to the usual System.out and your FileOutputStream.
Theres also an implementation of the TeePrintStream here http://www.java2s.com/Code/Java/File-Input-Output/TeePrintStreamteesallPrintStreamoperationsintoafileratherliketheUNIXtee1command.htm
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
public class SO34042494 {
public static void main(String[] args) throws FileNotFoundException {
System.setOut(new TeePrintStream(System.out, new FileOutputStream(new File("x:\\output.txt"))));
System.out.println("Check check");
System.out.println("1");
System.out.println(2);
System.out.println(3L);
}
public static class TeePrintStream extends PrintStream {
private final OutputStream tee;
public TeePrintStream(PrintStream original, OutputStream tee) {
super(original);
this.tee = tee;
}
#Override
public void write(byte[] b) throws IOException {
super.write(b);
tee.write(b);
}
#Override
public void write(byte[] buf, int off, int len) {
super.write(buf, off, len);
try {
tee.write(buf, off, len);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
public void write(int b) {
super.write(b);
try {
tee.write(b);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
public synchronized void close() {
try {
tee.close();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
super.close();
}
}
}
}
The TeePrintStream I have here is something I just threw together, please if your going to use this in a production project polish it up and test it thoroughly
Okej i think i solved it. In my main i just did like this:
public static void main(String[] args) {
Prinstream out = new Prinststream(file);
/*
Do some things like start threads, call objects etc..
.
.
.
.
*/
System.setOut(out);
I think that when all threads are started and doing their things(i do assign a object to each thread) the printstream will catch every console-output that occurs in other classes.
This didn't work before i edited my stopExecute class.
public class stopExecute implements Runnable {
Scanner scan = new Scanner(System.in);
private Object[] obj;
public stopExecute(Object[] obj)
{
this.obj = obj;
}
public void run() {
while(true){
stop();
}
}
public void stop() {
if(scan.hasNextLine()){
System.out.println("Stopped");
System.exit(0);
}
}
}
Thank you for your help guys. I will look into your suggestions and try them. In this solution i'm unable to use Log4J. But i will definitely check it out.

How do I get join() or wait() to work here? Java threads and concurrency

The code in this question was clearly too long so I've written an example you can just copy and paste that I think encompasses the conceptual problem I'm having.
Thanks to those who read all the way through the previous version!
Two files
One calls the other and passes an ArrayList.
The 2nd file alters the ArrayList and provides a getter for the first file to access the altered file.
How can I make the first file wait for the processing in the second file, before calling the getter. At the moment this code gives you a NullPointerException because the first file isn't waiting.
join() on the thread of execution doesn't seem to work, and if I use wait(), how do I notify() to the first file from the second file?
Here's the code:
public class Launcher implements Runnable {
private ArrayList al = new ArrayList();
private ArrayProcessor ap;
public Launcher(ArrayList al){
this.al = al;
ArrayProcessor ap = new ArrayProcessor(al);
}
public static void main(String[] args){
ArrayList anArray = new ArrayList();
anArray.add(new Integer(1));
anArray.add(new Integer(13));
anArray.add(new Integer(19));
Launcher l = new Launcher(anArray);
l.liftOff();
}
public void liftOff(){
Thread t = new Thread(new Launcher(al));
synchronized(t){
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.ap = new ArrayProcessor(al);
System.out.println("the array: " + ap.getArray());
}
public void run() {
ap.doProcess(al);
}
}
and the called file:
public class ArrayProcessor extends Thread{
private ArrayList al;
public ArrayProcessor(ArrayList al){
this.al = al;
}
public void doProcess(ArrayList myAL){
this.start();
}
public void run() {
// this should increment the ArrayList elements by one
for (int i=0; i<al.size(); i++){
int num = ((Integer)al.get(i)).intValue();
al.set(i, new Integer(++num));
}
}
public ArrayList getArray(){
return al;
}
}
If you want one thread wait for another to finish you could use a CountDownLatch. Since there is a lot of code in your samples, here is a small POC:
public static void main(String[] args) throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println("Thread doing some work...");
Thread.sleep(10 * 1000);
System.out.println("Thread done!");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
System.out.println("Main Thread waiting...");
latch.await();
System.out.println("Main Thread can continue");
}

Problem getting output and passing input to a executing process running under java

I am trying to call a simple program test.exe which is as simple as-
int main()
{
int a;
cout<<"Welcome\n";
while(cin>>a&&a!=0)
cout<<"you entered "<<a<<endl;
}
I want to run it from a java program as a process, and send+recieve i/o from it. I am using the process with 2 threads as follows-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Processproblem {
public static void main(String[] args)throws IOException, InterruptedException {
final Process process;
try {
process = Runtime.getRuntime().exec("test.exe");
} catch (IOException e1) {
e1.printStackTrace();
return;
}
new Thread(new Runnable() {
public void run() {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
while ((line = br.readLine()) != null) {
System.out.println("[OUT] " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
public void run() {
try {
byte[] buffer = new byte[1024];
int reading=0;
System.out.println(reading);
BufferedWriter bw= new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
while(reading!=-1)
{
reading= System.in.read(buffer);
for(int i = 0; i < buffer.length; i++) {
int intValue = new Byte(buffer[i]).intValue();
if (intValue == 0) {
reading = i;
break;
}
else
{
bw.append((char)intValue);
}
}
bw.newLine();
bw.flush();
}
} catch (Exception e) {
}
}
}
).start();
}
}
But they are not working as expected. When i run the program it just shows the "Welcome\n" message and then stops for input. When i give a integer and press enter in the java console it does nothing.
What am I doing wrong? They are two separate threads so why are they blocking each other? Is there any problem in my concept?
The program waits for your input. Grab the process output stream (using getOutputStream) and write to it.

Categories

Resources