Java - StringBuilder not accessible after while loop in thread - java

class myThread extends Thread {
myThread(Socket socket) {
Scanner sc = new Scanner(socket);
}
public void run() {
StringBuilder sb = new StringBuilder();
try {
while(sc.hasNext()) {
sb.append(sc.next());
sb.append(" ");
}
System.out.println(sb.toString());
} catch (Exception e) {
System.out.println(e);
}
}
This code doesn't output anything. However, If I move the System.out.println(sb.toString()); into the while loop, it does.
I have no idea why this is, but I need the code to output first AFTER the while loop is complete.
How would one go about to print the StringBuilder.toString() after the while-loop is complete?

The socket is probably never being closed, and the scanner is just blocking on hasNext().
Close the socket and it should finish.

Related

how can I stop the execution of the while loop with a keyboard input?

I have several threads. Each thread haves a while(true) loop inside, where I add cycle-by-cycle text. I don't find a good method to change the while(true) loop with a flag, in such a way that I can close the file when I come out from the cycle. I want to do this when I type something for example, or when I press the Eclipse red button.
This is the constructor (Node is a Thread)
public Node(Channel c, int address) {
my_address=address;
try {
writer = new CSVWriter(new FileWriter(my_address + "_id.csv"), ',', ' ' , ' ' ,"\n");
writer2 = new CSVWriter(new FileWriter(my_address + "_label.csv"), ',', ' ' , ' ' ,"\n");
String[] entries = "num#state#duration#event#condition#condition result#action1#action2#backoff value".split("#");
writer.writeNext(entries);
writer2.writeNext(entries);
} catch (IOException e) {
e.printStackTrace();
}
}
This is the loop in which I modify the file:
while (true) {
//write id value
String id_to_split = num+"#"+fsm.current_state.nome+"#"+tempo_minore+"#"+
fsm.current_transition.e.getId()+"#"+ fsm.current_transition.c.getId()+"#"+
fsm.current_transition.c.getFlag()+"#"+fsm.current_transition.a.getId()+"#"+
fsm.current_transition.a2.getId()+"#"+backoff;
String[] id_entries = id_to_split.split("#");
writer.writeNext(id_entries);
//write name
String label_to_split = num+"#"+fsm.current_state.nome+"#"+tempo_minore+"#"+
fsm.current_transition.e.getLabel()+"#"+fsm.current_transition.c.getLabel()+"#"+
fsm.current_transition.c.getFlag()+"#"+fsm.current_transition.a.getLabel()+"#"+
fsm.current_transition.a2.getLabel()+"#"+backoff;
String[] label_entries = label_to_split.split("#");
writer2.writeNext(label_entries);
num++;
}
closeCSVs();
}
The method closeCSVs():
public void closeCSVs() {
try {
writer.close();
writer2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
If I understood your question correctly, what you're looking for is either a try-with-resources block which works like following:
try(FileReader reader = new FileReader("path")) {
while(true) {
//use resources
}
}
You can use this with any Class that implements the AutoClosable-Interface (basically every class that offers a .close()-Method).
The resource will be closed automatically after the try-block is escaped.
Same solution different code would be to wrap with a classic try and adding a finally block to it.
try {
FileReader reader = new FileReader("path");
while(true) {
//use resources
}
} finally {
reader.close();
}
You may need to implement closing file in shutdown hook Runtime.addShutdownHook

Java reading console input in thread while listening for sockets in main thread

I'm fairly new to sockets and using threads in this way.
I am running into a problem with a scanner waiting for user input and an input stream reader waiting for socket communication at the same time. My program is trying to communicate with a client/server system, and that works fine, however I'm also wanting to be able to input commands into the console directly via a scanner or something similar. However the main thread's while loop is blocking for socket communication, while the scanner is blocking in the inputThread's while loop.
My problem is that if I send the command in the console to close the server (sets the bool 'running' to false), the main thread's while loop still waits for socket communication input. Once it receives any message it'll escape from the while loop due to the bool 'running' being set to false, but only once any message is sent due to it waiting for one before checking the while's conditional.
My other problem is basically the same concept, but inside the inputThread's while loop. If the main thread's while loop breaks then the input thread still has the scanner blocking until it receives user input. Once it receives any user input it'll escape from the while loop due to the thread being interrupted (while loop's conditional).
So in order for my program to exit I have to send the "restart server" message via sockets and user input, when I'd like to send it either way for the program to correctly exit.
How would I solve this problem? I'd assume by cancelling the scanner's blocking when I receive the socket to end the server, but how would I do that? I feel like there's a much better way to do this, any ideas?
Code:
inputThread = new Thread(new Runnable() {
#Override
public void run() {
Logger.log("Starting input thread...");
while(!Thread.currentThread().isInterrupted()) {
try {
scanner = new Scanner(System.in);
String reply = runCommand(scanner.nextLine());
Logger.log(reply);
if(reply.equals("server restarted")) {
// TODO: Cancel socket input blocking?
}
} catch(Exception e) {
e.printStackTrace();
}
}
Logger.log("Closing input thread...");
}
});
inputThread.start();
ServerSocket socket = null;
InputStreamReader inputStream = null;
BufferedReader input = null;
try {
int port = getPort();
socket = new ServerSocket(port);
Logger.log("Server running on port " + port);
while(running) {
connection = socket.accept();
inputStream = new InputStreamReader(connection.getInputStream());
input = new BufferedReader(inputStream);
String reply = runCommand(input.readLine());
if(reply.equals("server restarted")) {
// TODO: Cancel scanner input blocking?
}
reply(reply);
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if(socket != null) {
try {
socket.close();
} catch(IOException e) {
e.printStackTrace();
}
}
if(connection != null) {
try {
connection.close();
} catch(IOException e) {
e.printStackTrace();
}
}
if(inputStream != null) {
try {
inputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
}
if(input != null) {
try {
input.close();
} catch(IOException e) {
e.printStackTrace();
}
}
if(response != null) {
try {
response.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
inputThread.interrupt();
Thank you for reading
The first problem is the ServerSocket::acceptcall. It is blocking, but not responsive to interruption (if it were it would be declared to throw InterruptedException). The way to unblock it immediately is to close the socket from the other thread. The accept() call will then immediately throw a SocketException.
The second problem is actually simpler to solve : the while loop should also be checking the running flag. So when a command line input is given to stop the program, the input thread doesn't start waiting for the next command.

Running threads in round robin fashion in java

I am new to Multithreading and synchronization in java. I am trying to achieve a task in which i am given 5 files, each file will be read by one particular thread. Every thread should read one line from file then forward execution to next thread and so on. When all 5 threads read the first line, then again start from thread 1 running line no. 2 of file 1 and so on.
Thread ReadThread1 = new Thread(new ReadFile(0));
Thread ReadThread2 = new Thread(new ReadFile(1));
Thread ReadThread3 = new Thread(new ReadFile(2));
Thread ReadThread4 = new Thread(new ReadFile(3));
Thread ReadThread5 = new Thread(new ReadFile(4));
// starting all the threads
ReadThread1.start();
ReadThread2.start();
ReadThread3.start();
ReadThread4.start();
ReadThread5.start();
and in ReadFile (which implements Runnable, in the run method, i am trying to synchronize on bufferreader object.
BufferedReader br = null;
String sCurrentLine;
String filename="Source/"+files[fileno];
br = new BufferedReader(new FileReader(filename));
synchronized(br)
{
while ((sCurrentLine = br.readLine()) != null) {
int f=fileno+1;
System.out.print("File No."+f);
System.out.println("-->"+sCurrentLine);
br.notifyAll();
// some thing needs to be dine here i guess
}}
Need Help
Though this is not an ideal scenario for using multi-threading but as this is assignment I am putting one solution that works. The threads will execute sequentially and there are few point to note:
Current thread cannot move ahead to read the line in the file until and unless its immediately previous thread is done as they are supposed to read in round-robin fashion.
After current thread is done reading the line it must notify the other thread else that thread will wait forever.
I have tested this code with some files in temp package and it was able to read the lines in round robin fashion. I believe Phaser can also be used to solve this problem.
public class FileReaderRoundRobinNew {
public Object[] locks;
private static class LinePrinterJob implements Runnable {
private final Object currentLock;
private final Object nextLock;
BufferedReader bufferedReader = null;
public LinePrinterJob(String fileToRead, Object currentLock, Object nextLock) {
this.currentLock = currentLock;
this.nextLock = nextLock;
try {
this.bufferedReader = new BufferedReader(new FileReader(fileToRead));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
#Override
public void run() {
/*
* Few points to be noted:
* 1. Current thread cannot move ahead to read the line in the file until and unless its immediately previous thread is done as they are supposed to read in round-robin fashion.
* 2. After current thread is done reading the line it must notify the other thread else that thread will wait forever.
* */
String currentLine;
synchronized(currentLock) {
try {
while ( (currentLine = bufferedReader.readLine()) != null) {
try {
currentLock.wait();
System.out.println(currentLine);
}
catch(InterruptedException e) {}
synchronized(nextLock) {
nextLock.notify();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
synchronized(nextLock) {
nextLock.notify(); /// Ensures all threads exit at the end
}
}
}
public FileReaderRoundRobinNew(int numberOfFilesToRead) {
locks = new Object[numberOfFilesToRead];
int i;
String fileLocation = "src/temp/";
//Initialize lock instances in array.
for(i = 0; i < numberOfFilesToRead; ++i) locks[i] = new Object();
//Create threads
int j;
for(j=0; j<(numberOfFilesToRead-1); j++ ){
Thread linePrinterThread = new Thread(new LinePrinterJob(fileLocation + "Temp" + j,locks[j],locks[j+1]));
linePrinterThread.start();
}
Thread lastLinePrinterThread = new Thread(new LinePrinterJob(fileLocation + "Temp" + j,locks[numberOfFilesToRead-1],locks[0]));
lastLinePrinterThread.start();
}
public void startPrinting() {
synchronized (locks[0]) {
locks[0].notify();
}
}
public static void main(String[] args) {
FileReaderRoundRobinNew fileReaderRoundRobin = new FileReaderRoundRobinNew(4);
fileReaderRoundRobin.startPrinting();
}
}
If the only objective is to read the files in round-robin fashion and not strictly in same order then we can also use Phaser. In this case the order in which files are read is not always same, for example if we have four files (F1, F2, F3 and F4) then in first phase it can read them as F1-F2-F3-F4 but in next one it can read them as F2-F1-F4-F3. I am still putting this solution for sake of completion.
public class FileReaderRoundRobinUsingPhaser {
final List<Runnable> tasks = new ArrayList<>();
final int numberOfLinesToRead;
private static class LinePrinterJob implements Runnable {
private BufferedReader bufferedReader;
public LinePrinterJob(BufferedReader bufferedReader) {
this.bufferedReader = bufferedReader;
}
#Override
public void run() {
String currentLine;
try {
currentLine = bufferedReader.readLine();
System.out.println(currentLine);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public FileReaderRoundRobinUsingPhaser(int numberOfFilesToRead, int numberOfLinesToRead) {
this.numberOfLinesToRead = numberOfLinesToRead;
String fileLocation = "src/temp/";
for(int j=0; j<(numberOfFilesToRead-1); j++ ){
try {
tasks.add(new LinePrinterJob(new BufferedReader(new FileReader(fileLocation + "Temp" + j))));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
public void startPrinting( ) {
final Phaser phaser = new Phaser(1){
#Override
protected boolean onAdvance(int phase, int registeredParties) {
System.out.println("Phase Number: " + phase +" Registeres parties: " + getRegisteredParties() + " Arrived: " + getArrivedParties());
return ( phase >= numberOfLinesToRead || registeredParties == 0);
}
};
for(Runnable task : tasks) {
phaser.register();
new Thread(() -> {
do {
phaser.arriveAndAwaitAdvance();
task.run();
} while(!phaser.isTerminated());
}).start();
}
phaser.arriveAndDeregister();
}
public static void main(String[] args) {
FileReaderRoundRobinUsingPhaser fileReaderRoundRobin = new FileReaderRoundRobinUsingPhaser(4, 4);
fileReaderRoundRobin.startPrinting();
// Files will be accessed in round robin fashion but not exactly in same order always. For example it can read 4 files as 1234 then 1342 or 1243 etc.
}
}
The above example can be modified as per exact requirement. Here the constructor of FileReaderRoundRobinUsingPhaser takes the number of files and number of lines to read from each file. Also the boundary conditions need to be taken into consideration.
You are missing many parts of the puzzle:
you attempt to synchronize on an object local to each thread. This can have no effect and the JVM may even remove the whole locking operation;
you execute notifyAll without a matching wait;
the missing wait must be at the top of the run method, not at the bottom as you indicate.
Altogether, I'm afraid that fixing your code at this point is beyond the scope of one StackOverflow answer. My suggestion is to first familiarize yourself with the core concepts: the semantics of locks in Java, how they interoperate with wait and notify, and the precise semantics of those methods. An Oracle tutorial on the subject would be a nice start.

Read the 30Million user id's one by one from the big file

I am trying to read a very big file using Java. That big file will have data like this, meaning each line will have an user id.
149905320
1165665384
66969324
886633368
1145241312
286585320
1008665352
And in that big file there will be around 30Million user id's. Now I am trying to read all the user id's one by one from that big file only once. Meaning each user id should be selected only once from that big file. For example, if I have 30Million user id's then it should print 30 Million user id only once with the use of Multithreading code.
Below is the code I have which is a multithreaded code running with 10 threads but with the below program, I am not able to make sure that each user id is selected only once.
public class ReadingFile {
public static void main(String[] args) {
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
service.submit(new FileTask());
}
}
}
class FileTask implements Runnable {
#Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("D:/abc.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
//do things with line
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Can anybody help me with this? What wrong I am doing? And what is the fastest way to do this?
You really can't improve on having one thread reading the file sequentially, assuming that you haven't done anything like stripe the file across multiple disks. With one thread, you do one seek and then one long sequential read; with multiple threads you're going to have the threads causing multiple seeks as each gains control of the disk head.
Edit: This is a way to parallelize the line processing while still using serial I/O to read the lines. It uses a BlockingQueue to communicate between threads; the FileTask adds lines to the queue, and the CPUTask reads them and processes them. This is a thread-safe data structure, so no need to add any synchronization to it. You're using put(E e) to add strings to the queue, so if the queue is full (it can hold up to 200 strings, as defined in the declaration in ReadingFile) the FileTask blocks until space frees up; likewise you're using take() to remove items from the queue, so the CPUTask will block until an item is available.
public class ReadingFile {
public static void main(String[] args) {
final int threadCount = 10;
// BlockingQueue with a capacity of 200
BlockingQueue<String> queue = new ArrayBlockingQueue<>(200);
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < (threadCount - 1); i++) {
service.submit(new CPUTask(queue));
}
// Wait til FileTask completes
service.submit(new FileTask(queue)).get();
service.shutdownNow(); // interrupt CPUTasks
// Wait til CPUTasks terminate
service.awaitTermination(365, TimeUnit.DAYS);
}
}
class FileTask implements Runnable {
private final BlockingQueue<String> queue;
public FileTask(BlockingQueue<String> queue) {
this.queue = queue;
}
#Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("D:/abc.txt"));
String line;
while ((line = br.readLine()) != null) {
// block if the queue is full
queue.put(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class CPUTask implements Runnable {
private final BlockingQueue<String> queue;
public CPUTask(BlockingQueue<String> queue) {
this.queue = queue;
}
#Override
public void run() {
String line;
while(true) {
try {
// block if the queue is empty
line = queue.take();
// do things with line
} catch (InterruptedException ex) {
break; // FileTask has completed
}
}
// poll() returns null if the queue is empty
while((line = queue.poll()) != null) {
// do things with line;
}
}
}
We are talking about an average of a 315 MB file with lines separated by new line. I presume this easily fits into memory. It is implied that there is no particular order in the user names that has to be conserved. So I would recommend the following algorithm:
Get the file length
Copy each a 10th of the file into a byte buffer (binary copy should be fast)
Start a thread for processing each of these buffers
Each thread processes all lines in his area except the first and last one.
Each thread must return the first and last partitial line in its data when done,
the “last” of each thread must be recombined with the “first” one of the one working on the next file block because you may have cut through a line. And these tokens must then be processed afterwards.
Fork Join API introduced in 1.7 is a great fit for this use case. Check out http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html. If you search, you are going to find lots of examples out there.

Get input from the keyboard without pausing the program

I'm writing Java on Windows 7, and I want to be able to work with the input from the keyboard, which I can only presume is the standard input.
I've tried to use BufferedInput, System.in, and Scanner, but all of them require the program to pause and wait for an end of line or return! Is there anyway to just collect and record the data as it is used, and not have to wait for a return?
Here is a quick solution:
public static void main(String[] args) {
Thread inputThread = new Thread(new Runnable() {
#Override
public void run() {
Scanner scan = new Scanner(System.in);
String input = "";
while (true) {
System.out.println("Type something: ");
input = scan.nextLine();
System.out.println("Input: "+input);
}
}
});
inputThread.start();
while (true) {
System.out.println("");
System.out.println("test");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The main thread prints "test" every second. And the inputThread asks the user to type something then prints what he wrote. It's just a "visual" solution, you certainly don't want to print something while the user is typing.

Categories

Resources