0

我有一堂课,

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);
   }
}

上面的类编译得很好。但是在运行时,system.out.println() 中会抛出错误,说“无效的线程访问”。

代码中是否有任何错误。不允许在多线程中访问实例变量?有什么方法可以访问线程内的实例变量吗?

提前致谢。

编辑新:重现问题

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();
    }

} 

上面的代码会先抛出无效的线程访问 ecpection @printInstanceVariables() system.out.println()

答:知道了。这是因为在 printInstanceVariables() 中访问了线程内部的组件 Text。当我将此组件作为参数传递时,一切正常。感谢您的所有回答。

4

3 回答 3

3

该程序按预期编译和执行(它打印一个空格和一个新行)。您的问题在其他地方:

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);
        }
    }
}
于 2013-06-04T10:43:23.013 回答
1

我在没有扩展 B 类的情况下尝试了您的代码,并且它工作正常。你的B类包含什么?真的有必要扩展B类吗?

于 2013-06-04T10:42:18.813 回答
-2

匿名内部类只允许访问 FINAL 成员变量。这是 JVM 规范。我怀疑为什么编译代码时没有警告。


事实上,当运行这些代码时,我什么也得不到。有什么不对?


我重写代码,测试它并找到在此处输入图像描述

当线程在匿名内部类中时,它不能访问成员变量。请查看 eclipse 的输出。

在此处输入图像描述

于 2013-06-04T10:38:20.223 回答