I have problem with synchronized reading of my file. The case is simple: to handle data in the file. My problem is synchronization. I try to make it on object reader of class BufferedReader, but I have two problems. If I initialise reader in "try with resourses" of my method read() I will get to different objects of BufReader for the same object when I use it in different theads. The second one I initialise it in class and get the same object for threads, but a great problem with exeptions and unpredictable behavior. I will write code for the second situation. Can you advice me how to solve. I am studying now, that's why I want advices.
class FileReaderClass {
private File file = new File("src\\exer1\\Transfers.txt");
private BufferedReader reader = null;
private FileReader fr = null;
StringBuilder sb = new StringBuilder();
void read() throws IOException {
try {
fr = new FileReader(file);
reader = new BufferedReader(fr);
String buftext;
while ((buftext = reader.readLine()) != null){
synchronized (reader) {
System.out.println(Thread.currentThread().getName());//for testing
sb.append(buftext).append("\n");
//System.out.println(buftext);
}
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (reader != null)
reader.close();
if (fr != null)
fr.close();
}
}
}
class Reader1 implements Runnable {
private FileReaderClass frc;
public Reader1(FileReaderClass frc) {
this.frc = frc;
}
#Override
public void run() {
try {
frc.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Ex1 {
public static void main(String[] args) throws InterruptedException {
FileReaderClass frc = new FileReaderClass();
Thread t1 = new Thread(new Reader1(frc));
Thread t2 = new Thread(new Reader2(frc));
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("---------------------");
System.out.println(frc.sb);
}
}
You are sharing the same FileReaderClass instance (that is frc) in two threads. Your FileReaderClass is not thread safe, that causes the problems. There are two alternatives here:
Create another instance of FileReaderClass, so that both threads will use different instances.
Mark the method read as snychronized.
You are synchronizing on the wrong level. Your sync guard is useless, as there are actually two readers. That's because each time read is called, a reader will be created, which will be a separate instance. We can't even know for sure, which reader instance was the subject of syncing.
If you want to parallelize reading of your file you should use the same reader but use proper synchronization for each read by any thread, so that it stays consistent, the easiest way is to make the whole read method synchronized and instantiate your readers in your class constructor.
As you may want to read and write to your string builder in the correct order, the thread that reads a line must only release the lock after it writes to StringBuilder, making your whole method to be pretty much guarded by a lock. It will work but you won't gain any performance, and for small files it may cause too much overhead, but as an exercise it may suffice.
Your code as it is has the following problems
You are always creating new readers, thus every thread calling this method will start from the beginning.
As previously stated by another answear you are synchronizing at the wrong level, any thread may read and the thread scheduler can suspend it right after, causing your writes to StringBuilder object to be out of order (i think it is not intended).
Related
I was learning multithreading and wanted to read multiple text files in different threads simultaneously using different threads and get the result in single list. I have text files with First name and Last name of employees.
I have written following Employee class.
class Employee {
String first_name;
String last_name;
public Employee(String first_name, String last_name) {
super();
this.first_name = first_name;
this.last_name = last_name;
}
}
Class for reading files, with List to store the objects.
class FileReading {
List<Employee> employees = new ArrayList<Employee>();
public synchronized void readFile(String fileName) {
try {
FileReader fr = new FileReader(new File(fileName));
BufferedReader br = new BufferedReader(fr);
String line;
while ((line = br.readLine()) != null) {
String[] arr = line.split("\\s+");
employees.add(new Employee(arr[0], arr[1]));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Class with main method and threads.
public class TestMultithreading {
public static void main(String[] args) {
final FileReading fr = new FileReading();
Thread t1 = new Thread() {
public synchronized void run() {
fr.readFile("file1.txt");
}
};
Thread t2 = new Thread() {
public synchronized void run() {
fr.readFile("file2.txt");
}
};
Thread t3 = new Thread() {
public synchronized void run() {
fr.readFile("file3.txt");
}
};
t1.start();
t2.start();
t3.start();
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(fr.employees.size());
}
}
Does using join() method ensure to finish the thread on which it was called and proceed to the other? If yes, what is the point of multithreading?
Is there any other way to ensure all threads run parallelly and collect result from them after they all finish in main() method?
All threads run in parallel, however your readFile method is synchronized, so only one thread can enter it at any time (per object). This is a good choice, since it prevents updating the ArrayList (which is not thread-safe) concurrently, but also means that at any time two threads will wait before entering the readFile method.
If you create three FileReading instances, your code will run in parallel.
The join() method performs another kind of synchronization: it blocks the calling thread until the run() method of the other thread exits. Hence you are certain that after the three joins in your code the three threads have already finished.
The other answer was very elucidative. Refer to it to understand how to solve your problem better. I will give you a recipe along with some explanation as well.
First, you don't need a FileReading class (bad abstraction BTW). Just Runnable instances (e.g. anonymous classes) which receive the filename to read data from and the destination list.
You pass these Runnables to Thread instance constructors and keep them in some list or set, so you can call thread.start() on each of them (i.e. with set.forEach()) and do the same to thread.join(). Nothing needs to be done within synchronized blocks or methods.
This way your main method will wait for all of those threads to finish, while still taking advantage of parallelism (there will be some waiting for slower files to finish but all the threads will still do their heavy work in parallel -- at least as far as the file system/storage allows it).
What you said about join() is true, but the possibility of threads to work in parallel before joins is also true. The point is that joins will only happen after each task is concluded. So the file tasks taking less time will all do their work in parallel. Slower tasks still will take advantage of parallelism as a whole while the main method is waiting on the concluded faster ones and next will be the slower ones until all of them have concluded and the main method is finally allowed to go on.
It's like baking a cake, you can do tasks in parallel for a while but all will have to join into a single recipient which goes in the oven in the end.
Second, it is better to create an atomically-insertable List (see for instance Collections.synchronizedList(new ArrayList<>()) or more modern syntax so you can pass it to the Runnables and let them populate it concurrently while still preventing running conditions. This is where synchronized code is needed, and it will already be provided internally in the created list.
Lastly, I don't think you should create one numbered Thread reference for each single file, thread1, thread2, etc. You should have a list of files and create the Threads on demand while traversing it, then storing the Threads in the mentioned set or list for referencing them all at once later as mentioned.
How to perform read and write operation by using thread synchronization.
Condition: If one file exists where writers may write information to, only one writer may write at a time. Confusion may arise if a reader is trying read at the same as a writer is writing. Since readers only look at the data, but do not modify the data, we can allow more than one reader to read at the same time.
//reader thread
class Read extends Thread {
static File Reader fr1 = null;
static Buffered Reader br1 = null;
static synchronized void reader() throws IO Exception {
String path ="C:/Users/teja/Documents/file1.txt";
fr1 = new File Reader(path);
br1 = new Buffered Reader(fr);
int i;
while ((i = br. read()) != -1)
System .out. print((char) i);
System .out. print ln();
}
public void run() {
try {
reader();
} catch (IO Exception e) {
e. print Stack Trace();
}
}
}
//writer code
class Writer extends Thread {
static Buffered Writer bw1 = null;
static File Writer fw1 = null;
static synchronized void writer() throws IO Exception {
Scanner scanner = new Scanner(System.in);
System .out .print ln("enter data to be added:");
String data = scanner. nextLine();
String path = "C:/Users/vt/Documents/file1.txt";
fw1 = new File Writer(path, true);
bw1 = new Buffered Writer(fw1);
bw1.newLine();
bw1.write(data);
bw1.flush();
scanner. close();
System. out . println("data added");
}
public void run() {
try {
writer();
} catch (IO Exception e) {
e. print Stack Trace();
}
}
}
//main method
public class File Read Write {
public static void main(String[] args) {
Read rd1 =new Read();
Read rd2=new Read();
Writer wt1=new Writer();
rd1.run();
rd2.run();
wt1.run();
rd1. run();
}
}
I am new to files and threading in java. I know this is not correct approach. Guide me.
If one file exists where writers may write information to, only one writer may write at a time. Confusion may arise if a reader is trying read at the same as a writer is writing. Since readers only look at the data, but do not modify the data, we can allow more than one reader to read at the same time.
There are two approaches to this.
(1) Either lock the resource and have the readers wait until the writer has completed the writing operation (or likewise, have a writer waits until all readers are done). This approach guarantees consistency, but can be slow if a lot of writers/readers are working on the resource at the same time (see Lock in java.util.concurrent.locks package).
(2) Keep an in-memory-version of the contents of the file that is served to readers only. When a change is made, this in-memory version is updated. Here, you'll have more speed, but you lose consistency and you'll need more memory.
The condition you want to avoid is generally referred as race condition and what you want to avoid it is a synchronization method between threads. There are more choices available but the most suitable for your case are mutex and read-write lock.
A mutex basically just lock the resource before any operation on the shared resource is performed, independently from the type of operation and free it after the operation is terminated. So a read will block the resource and any other operation, read or write will be blocked.
A write will block the resource too so again no other read or write operation can be performed before the action is terminated and mutex unlocked. So basically a mutex has 2 states: locked and unlocked.
read-write lock gives you more freedom based on the fact that read only operations do not result in inconsistencies. A read-write lock has 3 states: unlocked, read lock, write lock. A write lock works as a regular mutex blocking any other operation. A read lock on the contrary blocks only write operations.
I am not a Java expert but from this answer mutex in Java can be used as the following:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
private final Lock lock = new ReentrantLock(true);
lock.lock()
/*open file and do stuff*/
try {
// do something
} catch (Exception e) {
// handle the exception
} finally {
lock.unlock();
}
Instead here you can find a description of a read-write lock class.
From the implementation point of view you can create an instance of one of the two synchronization method and have your read/write thread instances keeping a reference to it, as an instance variable.
Is there a way to safely and immediately stop the execution of a Thread in Java? Especially, if the logic inside the run() method of the Runnable implementation executes only a single iteration and does not regularly check for any flag that tells it to stop?
I am building a Web Application, using which a user can translate the contents of an entire document from one language to another.
Assuming the documents are extra-large, and subsequently assuming each translation is going to take a long time (say 20-25 minutes), my application creates a separate Thread for each translation that is initiated by its users. A user can see a list of active translations and decide to stop a particular translation job if he/she wishes so.
This is my Translator.java
public class Translator {
public void translate(File file, String sourceLanguage, String targetLanguage) {
//Translation happens here
//.......
//Translation ends and a new File is created.
}
}
I have created a TranslatorRunnable class which implements the Runnable interface as follows:
public class TranslatorRunnable implements Runnable {
private File document;
private String sourceLanguage;
private String targetLanguage;
public TranslatorRunnable(File document, String sourceLanguage, String targetLanguage) {
this.document = document;
this.sourceLanguage = sourceLanguage;
this.targetLanguage = targetLanguage;
}
public void run() {
// TODO Auto-generated method stub
Translator translator = new Translator();
translator.translate(this.document, this.sourceLanguage, this.targetLanguage);
System.out.println("Translator thread is finished.");
}
}
I'm creating the thread for translating a document from an outer class like this:
TranslatorRunnable tRunnable = new TranslatorRunnable(document, "ENGLISH", "FRENCH");
Thread t = new Thread(tRunnable);
t.start();
Now my problem is how do I stop a translation process (essentially a Thread) when the user clicks on "Stop" in the GUI?
I have read a few posts on StackOverflow as well as on other sites, which tell me to have a volatile boolean flag inside the Runnable implementation, which I should check on regularly from inside the run() method and decide when to stop. See this post
This doesn't work for me as the run() method is just calling the Translator.translate() method, which itself is going to take a long time. I have no option here.
The next thing I read is to use ExecutorService and use its shutDownAll() method. But even here, I'd have to handle InterruptedException somewhere regularly within my code. This, is again out of the option. Referred this documentation of the ExecutorService class.
I know I cannot use Thread.stop() as it is deprecated and may cause issues with objects that are commonly used by all threads.
What options do I have?
Is my requirement really feasible without substantial changes to my design? If yes, please tell me how.
If it is absolutely necessary for me to change the design, could anyone tell me what is the best approach I can take?
Thanks,
Sriram
Is there a way to safely and immediately stop the execution of a Thread in Java?
No. each thread is reponsible to periodically check if it has been interrupted to exit as soon as possible
if (Thread.currentThread().isInterrupted() ) {
// release resources. finish quickly what it was doing
}
if you want a more responsive application, you have to change the logic (for example divide each job in smaller batches) so each thread does this checking more often than every 20-25 minutes
If you are the one that created the Translator class what's stopping you from adding some kind of value inside the function that is checked periodically and if needed stops reading the lines from file something like this
public static List<String> readFile(String filename)
{
List<String> records = new ArrayList<>();
try
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
String line;
while ((line = reader.readLine()) != null)
{
String[] split = line.split("\\s+");
records.addAll(Arrays.asList(split));
if (needsToStop) {
break; //Or throw exception
}
}
reader.close();
return records;
}
catch (Exception e)
{
System.err.format("Exception occurred trying to read '%s'.", filename);
e.printStackTrace();
return null;
}
}
Below is my code to extract text from a text file and displaying it on the console.
Could some one please tell me how to make this program run on multiple threads simultaneoulsly?
I would also like to know if multiple threads are being used in performing the task as the time taken to run the task is varied every time i run.??
//Code
import java.io.*;
import java.util.*;
class Extract{
static int i=0;
FileInputStream in;
BufferedReader br;
ArrayList<String> stringList;
String li;
Extract() throws FileNotFoundException
{
FileInputStream in = new FileInputStream("C:\\Users\\sputta\\workspace\\Sample\\src\\threads.txt");
br = new BufferedReader(new InputStreamReader(in));
stringList = new ArrayList<String>();
li=" ";
}
void call()
{
try{
while(li!=null)
{
String str = br.readLine();
stringList.add(str);
li=stringList.get(i);
if(li!=null)
{
System.out.println(li);
i++;
}
}
Thread.sleep(1000);
in.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
class Caller implements Runnable {
Extract target;
Thread t;
public Caller(Extract targ)
{
target = targ;
t = new Thread(this);
t.start();
System.out.println(t.isAlive());
}
public void run()
{
synchronized(target) { // synchronized block
target.call();
}
}
}
public class Sample {
public static void main(String args[]) throws FileNotFoundException
{
long startTime = System.currentTimeMillis();
System.out.println(startTime);
Extract target = new Extract();
Caller ob1 = new Caller(target);
Caller ob2 = new Caller(target);
Caller ob3 = new Caller(target);
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
}
}
It does not make much sense performance-wise to have multiple threads reading from the same file, due to the inevitable input/output (I/O) bottleneck.
Two things that can be done to improve the situation:
"Split" the file into smaller pieces and assign each such "split" to a different thread. This is the approach followed by Hadoop, but it does require copying each "split" before processing, so it is only beneficial for large files (say, at least 100 MB each, or much more).
Use 1 thread to read from the file into a "prefetch" buffer, in memory, and then process the input from the buffer, via multiple other threads. A variation of this approach would be for the prefetch thread to "feed" each of the "consumer" threads with data, before each of them starts. Obviously, the relative allocation of prefetch vs. processing across the threads, will yield varying results, so further tuning would be necessary, depending on the application.
Both approaches have limitations and do not guarantee performance improvements in all cases.
Reading a text file line-by-line from a single thread can be done at a speed of over 1 million lines/sec, but still the bottleneck will remain in I/O, as already discussed.
I am trying to create a java socket program with multithread concept.
Every single connection from client to the server is a thread.
Every client send their information to server.
I want to ask how to collect all value from the threads and put them all in an array of string?
Is needed to synchronized all this threads?
What the different if use only Thread t = new Thread() instead of Thread[] t = new Thread(client)?
Am i right for the beginning step with use Thread[] to collect all item from the threads?
Is it useful to use thread join()?
This is part which create thread,
public void listenSocket(int client){
int i=0;
Thread[] t = new Thread[client];
while(i<client){
ClientWorker w;
try{
w = new ClientWorker(server.accept());
t[i] = new Thread(w);
t[i].start();
System.out.println(t[i].getName());
} catch (IOException e) {
System.out.println("Accept failed: 4444");
System.exit(-1);
}
i++;
}
}
This is the part of what the thread doing
class ClientWorker implements Runnable{
Socket client;
String ip;
String load;
String data[]=new String[7];
ClientWorker(Socket client){
this.client = client;
}
public void setIP(String ip){
this.ip = ip;
}
public void setData(String load){
this.load = load;
}
public void getIP(){
System.out.println(ip);
}
public void getData(){
System.out.println(load);
}
public void run(){
BufferedReader in = null;
PrintWriter out = null;
XmlGenerator xml = new XmlGenerator();
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("in or out failed");
}
while(true){
try{
String a = in.readLine();
setData(a);
String b = client.getRemoteSocketAddress().toString();
setIP(b);
out.println(a);
getData();
getIP();
}
catch (IOException e) {
System.out.println("Read failed");
}
}
}
}`
i've read the topic about sync,callable thread but i found nothing.
sorry for repost.
There are two ways to answer this:
First way:
I want to ask how to collect all value from the threads and put them all in an array of string? Is needed to synchronized all this threads?
If you are going to collect the results that way, then yes it is necessary to explicitly synchronize the threads' use of that array.
What the different if use only Thread t = new Thread() instead of Thread[] t = new Thread(client)?
It is not clear what you mean, but either way if you have two threads accessing / updating the same data structure then they need to synchronize for the application to be reliable / portable.
Am i right for the beginning step with use Thread[] to collect all item from the threads?
It is one approach. But there are better approaches.
Is it useful to use thread join()?
If you are going to try to address this problem at this level, then it could be useful.
The problem is that your code doesn't give me much confidence that you have a clear idea of what you are doing. Or to put it another way, there is no evidence of a design. And it is not really possible to give you specific advice if we can't figure out how you think your code should work. The code certainly doesn't seem to line up with the things you are saying at the start of your question ...
The Second way to answer this is that from Java 5 onwards, the "java.util.concurrent" package provides a broad range of "off the shelf" components for implementing multi-threaded systems. What you seem to be trying to implement sounds like a good match for an ExecutorService. It can deal with all of the low-level details of creating and managing threads, and allows the application to get the results of each computation back via a Future. This takes away the need for explicit synchronization ... the ExecutorService and Future implementations take care of that.
So, my recommendation would be to read the Javadocs for ExecutorService, etcetera and figure out how to do what you are trying to do using that. Your code is likely to be better if you do it that way.