views:

49

answers:

3

I created one thread with java.sql.Connection and String parameters. But from within the thread, I observed that String value was available but Connection object was not. Any clues?

(Editing details into question):

Well, it seems the connection object is available, but closed inside the thread. Here's the code:

package com.catgen.helper;

import java.sql.Connection;

public class ImageCheckHelper extends Thread{

    public Connection conn = null;
    public String str = null;

    public ImageCheckHelper(Connection conn, String str){
        this.conn = conn;
        this.str = str;
        try{
            System.out.println("From inside the constructor");
            System.out.println((this.conn!=null)?"Connection is not null":"Connection is null");
            System.out.println((this.str!=null)?"String is not null":"String is null");
            System.out.println((this.conn.isClosed())?"Connection is closed.":"Connection is not closed");
            System.out.println("\n\n");
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void run(){
        try{
            System.out.println("From inside the thread");
            System.out.println((conn!=null)?"Connection is not null":"Connection is null");
            System.out.println((str!=null)?"String is not null":"String is null");
            System.out.println((conn.isClosed())?"Connection is closed.":"Connection is not closed");
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void initiateImageCheck(){
        this.start();
        return;
    }
}

And here's the output:

From inside the constructor
Connection is not null
String is not null
Connection is not closed



From inside the thread
Connection is not null
String is not null
Connection is closed.
A: 

[Content moved to question]

James
James - I've edited this to move your information to the question, as that's where it belongs. In future you can do this yourself via the "edit" button under the question. Don't add an answer unless it really is an answer to your problem (which in this case, it wasn't).
Andrzej Doyle
Oh I'm new to Stackoverflow. I didn't know about the edit functionality. Thanks anyways. :) I did that so that the code could be displayed properly.
James
Not the entire code exactly. I smell something fishy. Probably it is. I'll get back.
James
A: 

I don't see what your problem is - looking at the output, you can see that both the Connection and String are non-null within the constructor and when you come to run the thread.

The only difference is that the connection has been closed at some point between the thread being constructed, and the thread being run. Depending on how you provided the connection, and how other threads were using it, this is not particularly unusual. In any case, you should be looking at other threads calling close() on the same Connection object if you want to track this down.

As a general guideline, it's typically easiest to have each thread manage its own Connection, because otherwise you end up with some very tricky semantics about committing and closing them (as you've seen here). Sharing a connection between multiple threads can work, and on rare occasions is necessary, but in general it should be the exception rather than the rule.

Edit: Additionally, a lot of Connection implementations are not even threadsafe, so you can't really use them between multiple threads in a reliable fashion. If one thread is running a statement and you then try to use the connection on a different thread, bad things will happen. Even more justification to just give each thread its own connection and let it get on with what it wants to do, without having to engage in some kind of mutex synchronization (a bottleneck that removes some of the attraction of multithreading, too!).

Andrzej Doyle
Any idea how the connection can be made available(not closed) inside the thread?
James
James - the only way to do this is to **not close the connection elsewhere**. But as I've said, a better solution in general is to make sure each thread is using its own connection.
Andrzej Doyle
As you can see from the code, the connection isn't closed explicitly anywhere. It seems this happens implicitly.My requirement here is to create only one thread and pass on the Connection for further use. The use of thread is to let the user know that the process has initiated immediately after initiating the action, without having the user to wait till the action is completed.
James
I cant see from the code, as this isn't your entire codebase. What code calls the constructor? Where does *that code* get the connection from? Will that same connection be used elsewhere?
Andrzej Doyle
Not the entire code exactly. I smell something fishy. Probably it is. I'll get back.
James
Well, immediately after the thread was created, the normal flow used to continue, and close the connection in the end.Thanks a lot Andrzej. Appreciate your help.
James
A: 

Is another thread closing the connection between the time it is given to the constructor and the time it is used in the run() method? My guess is that the connection is closed after the call to initiateImageCheck() returns but before the run() method has got as far as the isClosed() check.

If not, do you have access to the JDBC driver's source code? I wonder if it is protecting itself against multi-threaded use.

Connections are not guaranteed to be thread-safe, so you should obtain the connection from within the thread that is going to use it.

You also have unsynchronized access to conn from two different threads. Public member variables are not a good idea either - especially in classes that need to be thread-safe.

richj
You have the complete code in front of you. The connection is not closed anywhere else in between.About the unsynchronized access, I did that to simplify the code here, as we have only one thread.
James
Well, immediately after the thread was created, the normal flow used to continue, and close the connection in the end.Thanks a lot richj.
James