0

I have a class like,

Class A extends B {

   String test = "";
   String first = "";

   public void testMethod() {
      new Thread() {
         public void run() {
           testThreadMethod();
         }
      }.start();

   }

   public void testThreadMethod() {
     System.out.println(first + " " + test);
   }
}

The above class compiles fine. But in run time, the error is thrown in system.out.println() saying "invalid thread access".

Is there any wrong in the code. Accessing instance variables in multithread not allowed? Is there any way to access the instance variable inside the thread?

Thanks in advance.

EDITED NEW: To Reproduce the problem

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

public class SWTView extends ViewPart{
    public static Display display;
    public static Shell shell;
    static Text sampleText;
    static String testField1 = "";
    static String firstField2 = "";
    public static void main(String[] args) {
        display = new Display();
        shell = new Shell(display);
        // Create a new Gridlayout with 2 columns 
        // where the 2 column do not have the 
        // same size
        GridLayout layout = new GridLayout(2, false);
        // set the layout of the shell
        shell.setLayout(layout);
        // Create a label and a button

        sampleText = new Text(shell, SWT.NONE);
        Label label = new Label(shell, SWT.NONE);
        label.setText("A label");
        Button button = new Button(shell, SWT.PUSH);
        button.setText("Press Me");

        // Create a new label that will spam two columns
        label = new Label(shell, SWT.BORDER);
        label.setText("This is a label");
        // Create new layout data
        GridData data = new GridData(GridData.FILL, 
                GridData.BEGINNING, true, false, 2, 1);
        label.setLayoutData(data);

        // Create a new label which is used as a separator
        label = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
        // Create new layout data
        data = new GridData(GridData.FILL, GridData.BEGINNING, true,
                false, 2, 1);
        data.horizontalSpan=2;
        label.setLayoutData(data);

        // Create a right aligned button
        Button b = new Button(shell, SWT.PUSH);
        b.setText("New Button");
        b.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                new Thread() {
                    public void run() {
                        printInstanceVariables();
                    }
                }.start();
                //showProgressBar() ---> // This is been implemented in another file which will shoe progress bar
            }
        });

        data = new GridData(GridData.END, GridData.BEGINNING, false,
                false, 2, 1);
        b.setLayoutData(data);


        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }

    public static void printInstanceVariables() {
        System.out.println("Text entered is :: " +sampleText.getText());
        System.out.println("test Field 1 is :: " + testField1);
        System.out.println("first Field 2 is :: " + firstField2);
    }


    @Override
    public void createPartControl(Composite arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setFocus() {
      shell.setFocus();
    }

} 

The above code will throw invalid thread acesses ecpection @ printInstanceVariables() first system.out.println()

Answer: Got it.. It is because of accessing the component Text inside the thread in printInstanceVariables(). When i pass this component as paramter, everything works fine. Thanks for all you answers.

AJJ
  • 3,570
  • 7
  • 43
  • 76
  • sorry.. mistakenly typed at end of testmethod. – AJJ Jun 04 '13 at 10:28
  • 1
    Try declaring `test` and `first` as `final` – cmbaxter Jun 04 '13 at 10:33
  • 2
    Is there a stack trace with the error? Please post the entire error message. There isn't anything special that you must do to access instance fields from a thread. – John B Jun 04 '13 at 10:34
  • 3
    @cmbaxter Why? There is no need. The program looks fine so the problem is in the code that has not been shown yet... – assylias Jun 04 '13 at 10:35
  • @cmbaxter Marking them as `final` will help to make them thread-safe but should not address this issue. There is no reason a thread may not access non-final fields. – John B Jun 04 '13 at 10:35
  • My thought was that you had an anonymous class accessing non final fields. – cmbaxter Jun 04 '13 at 10:38
  • @cmbaxter that would only be a problem if the variables were local. With instance variables it is not an issue. – assylias Jun 04 '13 at 10:38
  • There is nothing wrong with it. It works. I tried it! – xagyg Jun 04 '13 at 10:43
  • 1
    I tried it as well. Worked for me. – John B Jun 04 '13 at 10:44
  • I am executing this class with SWT view part. the class B in question is the ViewPart class and class A is my view. The class A will be executed when the view is loaded and the new thread inside the class will be executed on click of a button in the view. Since class A is not executed by new Thread, the instance variables are not accessible in new thread??? please let me know on this. – AJJ Jun 04 '13 at 10:46
  • What methods are declared in B? By the way, use `class` instead of `Class` to compile (typo I suspect). – xagyg Jun 04 '13 at 10:48
  • You should check this previous post: http://stackoverflow.com/questions/5980316/invalid-thread-access-error-with-java-swt – cmbaxter Jun 04 '13 at 10:51
  • @Rock123 To get better, faster help: build a [SSCCE](http://sscce.org): a simple example that reproduces your problem and that we can test. – assylias Jun 04 '13 at 11:14

3 Answers3

3

This program compiles and executes as expected (it prints a space and a new line). Your problem is somewhere else:

public class Test {

    public static void main(String[] args) throws Exception {
        A a = new A();
        a.testMethod();
    }

    static class A {

        String test = "";
        String first = "";

        public void testMethod() {
            new Thread() {
                public void run() {
                    testThreadMethod();
                }
            }.start();
        }

        public void testThreadMethod() {
            System.out.println(first + " " + test);
        }
    }
}
assylias
  • 321,522
  • 82
  • 660
  • 783
1

I tried your code without extending class B and its working fine. What does your class B contain? Is there really any need to extend class B?

Sumit Desai
  • 1,542
  • 9
  • 22
  • Good question. @Rock123 - what does B look like? – xagyg Jun 04 '13 at 10:46
  • I am executing this class with SWT view part. the class B in question is the ViewPart class and class A is my view. The class A will be executed when the view is loaded and the new thread inside the class will be executed on click of a button in the view. Since class A is not executed by new Thread, the instance variables are not accessible in new thread??? please let me know on this. – AJJ Jun 04 '13 at 10:49
  • @Rock123 The `new Thread` instance is an anonymous instance of `A` and therefore DOES have access to the fields of `A`. We have said this MULTIPLE times. Something ELSE is the issue. – John B Jun 04 '13 at 11:03
-2

anonymous inner class is only allowed access FINAL member variable. this is JVM specification. i doubt why there is no warning when your code be compiled.


in fact i could get nothing out put when run these code. is there something wrong?


i rewrite the codes, test it and find enter image description here

it can't access a member variable when the thread in anonymous inner class. please see the output from eclipse.

enter image description here

BrookLeet
  • 58
  • 2