views:

422

answers:

4

Hi Guys,

I think I have a synchronization problem...It may be too basic..Please help..

I have a thread the run method of which is below

 public void run()
    {
      while(true)
      {
            try {
                for (int i = 0; i < 100; i++) {
                    buf.append(hello + (myint++));
                }
                buf.append("\n");
                adapter.setData(buf.toString());
                buf = null;
                buf = new StringBuffer();
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(TestThread.class.getName()).log(Level.SEVERE, null, ex);
            }

      }

I am creating new string data in each run and passing it to the adapter class setData method..

In the adapter class my setData is like this..

public boolean setData(String sb){

     str = sb;
     if(str != null && !str.equalsIgnoreCase("")){
      timer.scheduleAtFixedRate(new TimerTask() {
                public void run() {


                            System.out.println("inside run.....");
                  System.out.println("str length:- "+str.length());
                                //do sth after this..

                                }
                     }

But once in a while I get null pointer exception at the line str.length()...I get this even when I try to create a new string with the buf.toString() in the first run method..

What am I doing wrong??

Thanks in advance..

+2  A: 

That is because the str is a class variable. If you don't have a reason for using another reference for sb, try this:

public boolean setData(final String str){

        if(str != null && !str.equalsIgnoreCase("")){
                timer.scheduleAtFixedRate(new TimerTask() {
                public void run() {


                            System.out.println("inside run.....");
                                System.out.println("str length:- "+str.length());
                                //do sth after this..

                                }
                     }
Zed
A: 

The problem is that you aren't synchronizing at all. For example, the "str" field is being read from one thread and simultaneously updated from another thread, without any synchronization.

(It would help if you showed a complete and runnable example instead of just the parts you think are interesting.)

JesperE
+1  A: 

What you are doing wrong is this: the buf and str are apparently both instance or static fields accessed unsynchronized by multiple threads.

It almost looks like you aren't aware of the concept of local variables. It looks as though both buf and str could be local variables (and str replaced by the sb method parameter). Try changing your code to this:

public void run()
{
  while(true)
  {
        try {
            StringBuffer buf = new StringBuffer();
            for (int i = 0; i < 100; i++) {
                buf.append(hello + (myint++));
            }
            buf.append("\n");
            adapter.setData(buf.toString());
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(TestThread.class.getName()).log(Level.SEVERE, null, ex);
        }

  }

public boolean setData(String str){
    if(str != null && !str.equalsIgnoreCase("")){
        timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            System.out.println("inside run.....");
            System.out.println("str length:- "+str.length());
            //do sth after this..
        }
    }

And remove the instance or class declarations of buf and str. If you actually need them outside the methods, try doing so via return values or, if all else fails, use synchronization.

Michael Borgwardt
Thanks for your answer. declaring str as final helped as pointed below..I need it in the inner class
Guru
It's not the "final" that helped! It's changing it to a local variable that did.
Michael Borgwardt
A: 

Try using get and set methods for the "str" which will be synchronized using a syncronization object:

private static Object syncObject = new Object();
public String getStr(){
  synchronized (syncObject){
    return str;
  }
}
public void setStr(String value){
  synchronized (syncObject){
    str = value;
  }
}

And insted:

str=sb;

try:

setStr(sb);

and insted:

System.out.println("str length:- "+str.length());

try:System.out.println("str length:- "+getStr().length());

igors