I am writing java program that creates different instances of Runnable objects given by someone and then runs them. For instance user gives me a .class file with runnable class and I create instance of that object and run it. Everything works fine until I decided to monitor every different thread's progress. Lets say that current Runnable object print all the numbers from 1 to 9 in console. I want to catch that output and return it as a String. Using System.setOut(..) prevents me from using console, so it is not an option.
Using setOut doesn't prevent you from using the console, if you save it first and it is your only option unless you use byte code instrumentation.
static final PrintStream OUT = System.out;
static {
// capture all System.out
System.setOut(new MyPrintStream());
OUT.println("Print as normal");
}
class MyPrintStream extends PrintStream {
final ThreadLocal<StringBuilder> text = ThreadLocal.withInitial(() _> new StringBuilder());
public void print(String s) {
StringBuilder sb = text.get();
sb.append(s);
}
public void println(String s) {
StringBuilder sb = text.get();
sb.append(s).append('\n');
// do something with sb.
}
Related
I don't know how to print to a text file when I'm using threads because every time it just creates another file, so I end up with just one result which is the last one, I have tried a lot of things and is always the same.
This is just a part of the code, besides printing to the file I have to print a graph too and I have the same problem as it creates one graph for each thread.
public class Adsda implements Runnable{
private int id=0;
public int number;
public String file="Time.txt";
private final PrintWriter outputStream;
public Adsda(int id) throws FileNotFoundException {
this.id=id+1;
this.outputStream=new PrintWriter(this.file);
}
public void run() {
int i,fact=1;
this.number=id;//It is the number to calculate factorial
long A=System.nanoTime();
for(i=1;i<=this.number;i++){
fact=fact*i;
}
long B=System.nanoTime();
long t=B-A;
double tt = (double)t / 1000000000.0;
System.out.println("Factorial of "+number+" is: "+fact+" Time: "+tt);
this.outputStream.println("Factorial of: "+this.number+" Time: "+tt);
this.outputStream.flush();
}
public static void main(String[] args) throws FileNotFoundException{
ExecutorService executor = Executors.newFixedThreadPool(2);//creating a pool of 2 threads
for(int i=0;i<5;i++){
executor.submit(new Adsda(i) );
}
executor.shutdown();
}
You should create a single PrintWriter and share that with the threads by passing it in the constructor instead of having each thread create their own PrintWriter (and file). Although that will result in the file containing the results in weird order. If you want to have them in a specific order, you should have the threads output their results in their own buffers and when all threads are finished, write the buffers out to a file in sequence.
PrintWriter pw = new PrintWriter(filename);
for(int i=0;i<5;i++){
executor.submit(new Adsda(i, pw) );
}
Just to answer your question, you have multiple threads that execute your run method and all of them will write the file named "Time.txt". You should write a file for each thread. Also you are sharing your output stream between multiple threads which is an issue in itself. Move the print writer creation in the run method and use a name like "time" + Thread.curentThread().getID() + ".txt". That should fix it.
SOLVED:
HovecraftFullOfEels found my mistake. See the comments on his answer below. I was calling run() on a Thread object when I should have been calling start(). In my original program, that meant it blocked on stderr until the program quit and then got stdout all at once.
UPDATE:
As requested, I've produced a minimal example. Here's the producer:
package producer;
public class Producer {
public static void main(String[] args) throws InterruptedException {
for (int i=0; i<10; i++) {
System.out.println(i);
System.out.flush();
Thread.sleep(1000);
}
}
}
Here's the consumer:
package consumer;
import java.io.IOException;
import java.io.InputStream;
public class Consumer {
static class Dumper extends Thread {
InputStream r;
boolean print;
Dumper(InputStream r, boolean print) {
this.r = r;
this.print = print;
}
#Override
public void run() {
int c;
try {
while ((c = r.read()) != -1) {
if (print) System.out.print((char)c);
}
r.close();
} catch (IOException ex) {}
}
}
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec("java -jar C:\\Users\\millerti\\Documents\\NetBeansProjects\\Producer\\dist\\Producer.jar");
new Dumper(p.getErrorStream(), false).run();
new Dumper(p.getInputStream(), true).run();
p.waitFor();
}
}
Expected behavior: Since the producer flushes its output and the consumer is completely unbuffered, the consumer should get the producer's output in real time.
Observed behavior: The consumer receives the producer's output all at once only when the producer finished.
Original post:
I'm working with another developer on a Windows application. She has written a C program (which we can modify) that performs a media conversion and prints progress messages (in percentage) to stdout. I am writing a graphical front-end in Java, and I would like my program to capture those messages and update a GUI element.
The relevant C program code looks like this:
printf ("progress_msg: %d%%\n", currentProgress);
fflush(stdout);
In the Java program, I'm using Runtime.getRuntime().exec() to run the C program and grabbing the raw InputStream objects for C program's stdout and stderr. (The stderr is just being thrown away by another thread.) I'm parsing the stdout stream, looking for those messages (well, I was, using a BufferedReader, but right now, I'm trying to debug this, so I'm talking directly to the low-level InputStream byte source.)
The problem is that although there is no buffering on the Java side (that I know of) and there's an fflush in the C program, the stdout text appears all at once only when the C program finishes. This is unlike when I run it from the command prompt, where the messages come out gradually as expected.
So clearly, there's some buffering going on. Is the Process facility in Java doing some buffering that I don't know about? If so, is there a way to turn it off? Does fflush(stdout) in Windows not work in the expected way? What is the proper Windows equivalent?
Thanks.
Note: I have found two related stackoverflows, but they do not answer this question. In particular, we CAN modify the C program, there's no line buffering, and we ARE doing a proper flush (as far as we know). See I want realtime output of my Runtime.getRuntime().exec() and Unbuffered subprocess stdout on windows.
A wild guess from my part, but you state:
... I am writing a graphical front-end in Java, and I would like my program to capture those messages and update a GUI element.
...
In the Java program, I'm using Runtime.getRuntime().exec() to run the C program and grabbing the raw InputStream objects for C program's stdout and stderr. ... I'm parsing the stdout stream, looking for those messages ...
The problem is that although there is no buffering on the Java side (that I know of) and there's an fflush in the C program, the stdout text appears all at once only when the C program finishes.
I again have to guess as you've left out important details, all code, but if your front end is a Swing GUI, then the symptoms you've described suggest that you're trying to get all information on the Swing event thread. If this is a Swing application, a solution is to make sure to read the output of the Stream in a background thread such as that provided by a SwingWorker, to make sure that you buffer this data that you're reading in, and to then display it in the GUI in a thread-safe way (again using a SwingWorker, especially its publish/process method pair).
For better help, please give us better information and code, preferably a small, in fact minimal, example program that we can run and test and improve.
Edit
My test program:
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Consumer {
static class StreamGobbler implements Runnable {
private String name;
private boolean print;
private Scanner scanner;
public StreamGobbler(String name, InputStream inputStream, boolean print) {
this.name = name;
this.print = print;
scanner = new Scanner(inputStream);
}
#Override
public void run() {
System.out.printf("in %s run method%n", name);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (print) {
String output = String.format("From %s: %s%n", name, line);
System.out.printf(output);
}
}
if (scanner != null) {
scanner.close();
}
}
}
private static final String PRODUCER_PATH = "C:/Users/Pete/Documents/Fubar/Java/producer.jar";
public static void main(String[] args) {
List<String> command = new ArrayList<>();
command.add("java.exe");
command.add("-jar");
command.add(PRODUCER_PATH);
try {
ProcessBuilder pBuilder = new ProcessBuilder(command);
Process process = pBuilder.start();
StreamGobbler errorGobbler = new StreamGobbler("Error Gobbler", process.getErrorStream(), true);
StreamGobbler inputGobbler = new StreamGobbler("Input Gobbler", process.getInputStream(), true);
new Thread(errorGobbler).start();
new Thread(inputGobbler).start();
process.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
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();
I have a method which takes a list and do some processing on it and it updates another global list. I need to run multiple instances of this method with different lists input in parallel.
Does multi-threading support this? If yes, how can i use it i.e.: what shall i put in the thread? Examples are highly appreciated.
I am thinking of having a static list in the thread class which gets updated by the different instances of the thread while running (the list contains strings and counters, so the update is adding new strings or increasing the counters of existing ones).. i need to read whatever gets added to this global list every 10 seconds and print it.. is using static list suitable for this and how can i make it thread safe?
Yes, that's a very common usage of multithreaded programming.
class ListProcessor implements Runnable {
/* field/s representing param/s */
public ListProcessor(/* param/s */) {
/* ... */
}
#Override
public void run() {
/* process list */
}
}
Then, when you want to actually process some lists.
class SomeClass {
ExecutorService listProcessor;
public SomeClass(/* ... */) {
listProcessor = ExecutorService.newFixedThreadPool(numThreads);
/* for each thread, however you want to do it */
listProcessor.execute(new ListProcessor(/* param/s */));
/* when finished adding threads */
listProcessor.shutdown();
/* note that the above two lines of code (execute/shutdown) can be
* placed anywhere in the code. I just put them in the constructor to
* facilitate this example.
*/
}
}
#purtip31 has a start for the parallel processing stuff.
I'm concerned about the results - you mention that you update a "global list". If multiple threads at a time are trying to update that list at the same time there could be problems. A couple of options:
Make sure that list is properly thread safe. This may or may not be easy - depends on exactly what is getting changed.
Use ExecutorService, but with the invokeAll() method, which runs a bunch of Callables in parallel and waits till they are all done. Then you can go through all of the results and update them one at a time. No threading issues with the results. This means that your code will have to implement Callable instead of Runnable (not a big deal). I have a blog with an example here
Well Sam...i m not much cleared with your question.....
try this out....
Following is a code which would help u to run mulitple instances.......
Main thread
public class mainprocess
{
public static LinkedList globallist;
public static String str;
public int num;
public static void main(String Data[])
{
globallist = new LinkedList();
// LinkedList will be passed as pass by reference.....
// globalist is made static and assigned likewise for global use..
childprocess.assignlist(globallist);
childprocess p1 = new childprocess("string input"); // a string input...
childprocess p2 = new childprocess(number input); // a number input...
p1.t.join();
p2.t.join();
}
}
The Child Thread.....
public class childprocess implements Runnable
{
public Thread t1,t2;
public boolean inttype,stringtype;
String string;
int num;
public static LinkedList temp = new Linkedlist();
public static assignlist(LinkedList ll)
{
temp = ll;
}
public childprocess(String str)
{
string = str;
t1 = new Thread(this,"stringThread");
t1.start();
}
#override
public childprocess(int n)
{
num = n;
t2 = new Thread(this,"numberThread");
t2.start();
}
#override
public void run()
{
// Both will be executed in a threader manner based on the condition...
if(Thread.currentThread().getName().equals("stringThread")
{
// your process using string......
childprocess.temp.add(str);
}
else if(Thread.currentThread().getName().equals("numberThread")
{
// your process using number.....
chilprocess.temp.add(num);
}
}
}
If you are using functions that should be restricted to only one thread at a time...
include the syntax....
public synchronized func_type func_name()
{
}
I'm writing a multithreaded Java program where each thread potentially needs its standard output redirected to a separate file. Each thread would have its own file. Is it possible to redirect System.out on a "per-thread" basis or are changes to System.out global across all threads?
Is it possible to redirect System.out on a "per-thread" basis
No it is not possible. System.out is static and there is one per JVM that is loaded as part of the system classloader when the JVM initially boots. Although of course using proper logging calls per-thread is recommend, I assume there are reasons why you can't do this. Probably a 3rd party library or other code is what is using System.out in this manner.
One thing you could do (as a radical suggestion) is to make your own PrintStream that delegates to a ThreadLocal<PrintStream>. But you will need to #Override the appropriate methods called by your application to get it to work per-thread.
Lastly, if you are asking this because you are worried about concurrency, System.out is a PrintStream so it is already synchronized under the covers and can be used safely by multiple threads.
Is it possible to redirect System.out on a "per-thread" basis
Some developers from Maia Company have provided a public implementation of a PrintStream that provides one "STDOUT" per thread in this article : "Thread Specific System.out".
In their implementation they override only write methods, flush, close and checkError. It seems to be enough in their case.
They did not "need to #Override all of the methods called to get it to work per-thread" as #Gray stated in his answer.
NOTA:
Please find below the original code from Maia.
I found it here on the wayback machine. The original page was removed from the website of Maia. I reproduce it here for the reader's curiosity. I do not provide any support for this code.
Main.java
Creates a ThreadPrintStream, installs it as System.out, and creates and starts 10 threads.
public class Main {
public static void main(String[] args) {
// Call replaceSystemOut which replaces the
// normal System.out with a ThreadPrintStream.
ThreadPrintStream.replaceSystemOut();
// Create and start 10 different threads. Each thread
// will create its own PrintStream and install it into
// the ThreadPrintStream and then write three messages
// to System.out.
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new StreamText());
thread.start();
// Report to the console that a new thread was started.
System.out.println("Created and started " + thread.getName());
}
}
}
StreamText.java
A simple Runnable for each thread that opens a file for the thread’s output and installs it into the ThreadPrintStream.
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.PrintStream;
/** A small test class that sets System.out for the currently executing
* thread to a text file and writes three messages to System.out. */
public class StreamText implements Runnable {
#Override
public void run() {
try {
// Create a text file where System.out.println()
// will send its data for this thread.
String name = Thread.currentThread().getName();
FileOutputStream fos = new FileOutputStream(name + ".txt");
// Create a PrintStream that will write to the new file.
PrintStream stream = new PrintStream(new BufferedOutputStream(fos));
// Install the PrintStream to be used as System.out for this thread.
((ThreadPrintStream)System.out).setThreadOut(stream);
// Output three messages to System.out.
System.out.println(name + ": first message");
System.out.println("This is the second message from " + name);
System.out.println(name + ": 3rd message");
// Close System.out for this thread which will
// flush and close this thread's text file.
System.out.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
ThreadPrintStream.java
Extends java.io.PrintStream. An object of ThreadPrintStream replaces the normal System.out and maintains a separate java.io.PrintStream for each thread.
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
/** A ThreadPrintStream replaces the normal System.out and ensures
* that output to System.out goes to a different PrintStream for
* each thread. It does this by using ThreadLocal to maintain a
* PrintStream for each thread. */
public class ThreadPrintStream extends PrintStream {
/** Changes System.out to a ThreadPrintStream which will
* send output to a separate file for each thread. */
public static void replaceSystemOut() {
// Save the existing System.out
PrintStream console = System.out;
// Create a ThreadPrintStream and install it as System.out
ThreadPrintStream threadOut = new ThreadPrintStream();
System.setOut(threadOut);
// Use the original System.out as the current thread's System.out
threadOut.setThreadOut(console);
}
/** Thread specific storage to hold a PrintStream for each thread */
private ThreadLocal<PrintStream> out;
private ThreadPrintStream() {
super(new ByteArrayOutputStream(0));
out = new ThreadLocal<PrintStream>();
}
/** Sets the PrintStream for the currently executing thread. */
public void setThreadOut(PrintStream out) {
this.out.set(out);
}
/** Returns the PrintStream for the currently executing thread. */
public PrintStream getThreadOut() {
return this.out.get();
}
#Override public boolean checkError() {
return getThreadOut().checkError();
}
#Override public void write(byte[] buf, int off, int len) {
getThreadOut().write(buf, off, len);
}
#Override public void write(int b) { getThreadOut().write(b); }
#Override public void flush() { getThreadOut().flush(); }
#Override public void close() { getThreadOut().close(); }
}
You are right but not in the way you think. When a thread uses
System.out.println();
It takes a copy of the reference System.out, but not a copy of the object this references.
This means all threads will normally see the same object for writing to output.
Note: This fields in not thread safe and if you call System.setOut(PrintStream) If you use this there is a potential, undesirable race condition where different threads to have different local copies of System.out. This cannot be used to solve this question.
Is it possible to redirect System.out on a "per-thread" basis
You can do this by replacing System.out with your own implementation which is thread specific. i.e. a sub class of PrintStream. I have done this for logging where I wanted each thread's output to be consistent and not interleaved. e.g. Imagine printing two stack traces in two threads at the same time. ;)
System.out is static, and therefore the same instance is shared between all threads.
Is it possible to redirect System.out on a "per-thread" basis
You can redirect them all to your delegate which will be responsible for 'per-thread' logic.
Here is example of parallel JBehave tests having theirs own file output.