File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
Win a copy of Clojure in Action this week in the Clojure forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Specific threads question....

 
Anthony Smith
Ranch Hand
Posts: 285
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a class that has a main, implements runnable...
Right now my main class will call one of my methods depending on my input

For this one particular method it opens a file and then creates threads calling their run methods via start().

My class has three members that I use
String buffer ="";
static BufferedReader dis;
static PrintWriter out;

In my method that creates the threads, I open a file for reading and open a file for writing.

In my run method, I use dis to read the file and out to write to the file. buffer is what I am reading from the input file, and buffer is also what
I am writing to the output file...

Originally, I was just reading from a file and doing no writing to a file.

Tis seemed to work:

synchronized(buffer){
buffer = dis.readLine();
out.println(buffer);
}

I thought that that kind of synchronization would work... For some reason, I don't think that is the best way...

What should I do so that a thread is not accessing the input and putput file at the same time?

Also, should I create a local variable in my run method to assign buffer to? I use buffer to perform some other operations later on in my run method...
 
David Harkness
Ranch Hand
Posts: 1646
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Keep in mind that synchronization locks are obtained on an instance of an object -- not on a reference variable. When you assign a new String to buffer, the other threads will now be able to synchronize on it since the current thread holds a lock on the String that buffer used to reference.

Instead, create a single object (heck, us an actual Object instance if you like) on which to synchronize, or synchronize on the instance of the main class itself by having the run() method call a synchronized method on the main class.

I definitely recommend making buffer local to the run() method since it's not shared across threads. I wonder, however, what the point of using multiple threads is if you're synchronizing access to the file. Does each thread's run() method look something like the following?
  • Synchronize on file
  • Read line
  • Process line
  • Write line back to file
  • Release lock on file

  • If so, then having multiple threads do this same loop adds only overhead since the whole set of five steps must occur in a block. If you describe what the purpose is in more detail we can offer other ideas.
    [ March 15, 2005: Message edited by: David Harkness ]
     
    Anthony Smith
    Ranch Hand
    Posts: 285
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ok, you kind of confused me just a bit...

    I do understand the part about making buffer local. I dont know why I tried to make it global. Now the making an object... I have no clue about that.

    Here is the method called from my main:
    public static void readFileAndRate(){

    String input = "C:\\autopay\\testfiles\\CO_OB.txt";
    try{
    InputStreamReader bis = new InputStreamReader(new FileInputStream(input));
    dis = new BufferedReader(bis);
    out = new PrintWriter(new FileOutputStream("OB_Status.txt"));
    }
    catch(Exception e){
    e.printStackTrace();
    }

    for (int i = 0; i!=10; i++){
    new Thread(new ECQSClientBeanTester()).start();
    }

    }

    *******************************************
    Here is my run Method:

    public void run(){

    try{
    while (true) {

    synchronized(buffer){
    buffer = dis.readLine();
    out.println(buffer);
    }

    Make some external calls to other methods with
    the value of buffer as my input
    ..........

    }
     
    Henry Wong
    author
    Marshal
    Pie
    Posts: 20836
    75
    C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    What you did is actually a pretty common mistake:



    Basically, synchronization is done with an object (as a monitor). Upon entry to synchronization, the JVM will grab the lock of the object referred to by the buffer variable.

    Changing the variable -- as you do in the next line -- is perfectly okay. But you have to understand, that if another thread does a synchronization on buffer, it is a different object, and hence, a different lock.

    Did you intend to have a different lock? Or are you assuming that all blocks that synchronized on the buffer variable are thread safe?

    Henry
     
    Anthony Smith
    Ranch Hand
    Posts: 285
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ah... Sounds like I need to get a java book... I have no idea what to do.
     
    Yuriy Zilbergleyt
    Ranch Hand
    Posts: 429
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Unless one of the other methods you call reassigns dis or out (or readFileAndRate() gets called again,) you can synchronize on either one of these:


    synchronized(dis){
    buffer = dis.readLine();
    out.println(buffer);
    }

    Since unlike buffer, dis always points to the same object, you'll never have more than one thread executing the synchronized block at a time.

    -Yuriy
     
    I agree. Here's the link: http://aspose.com/file-tools
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic