Java MULTITHREADING - 当多个线程访问print方法时 - 为什么默认同步执行while方法

时间:2011-04-27 05:59:57

标签: java

对多线程有疑问。 以下是我访问文件的主程序,我在对象上创建了10个线程。

public class CallTest {
    public static void main(String[] args) throws Exception {
        Test t = new Test();
        for (int i = 0; i < 10; i++) {
            Thread t1 = new Thread(t);

            t1.start();

        }

    }
}

以下是我从程序中读取数据的程序。

public class Test implements Runnable {
    static int i;
    public void run() {
        try {
            i++;
            System.out.println("@@@@Count" + i);
            print();
        } catch (Exception e) {}
    }

    public void print() {
        try {
            StringBuilder bufData = new StringBuilder();
            File fileTest = new File("D:\\Work\\i466477");
            BufferedReader bufferedReader1 = new BufferedReader(new FileReader(
                    fileTest));
            String strRecord = new String();
            while ((strRecord = bufferedReader1.readLine()) != null) {
                bufData.append(strRecord);
                bufData.append("\r");
                bufData.append("\n");
            }
            bufferedReader1.close();
            System.out.println("########");
            System.out.println(bufData);

        } catch (Exception exe) {
            System.out.println(exe);
        }
    }
}

在这里,我可以看到while中的代码默认是同步的,BufferedReader是线程安全的,或者因为每个线程都有自己的StringBuilderBufferedReader副本?我可以看到内容被正确读取和写入。

5 个答案:

答案 0 :(得分:4)

不,默认情况下,该代码不会同步。多个线程可以同时位于while循环中。 “同步”与“没有任何问题的工作”不一样 - 您认为它是否因为您没有任何问题而同步?在Java中,synchronized只允许一个线程一次执行与特定监视器相关的某些关键代码

请注意,顺便说一下,i方法对run的访问权限是不安全的。您还应关闭BufferedReader块中的finally,并避免捕获Exception。最后,您开始new String()strRecord的分配毫无意义。希望这些只是错误,因为它是测试代码,但值得了解它们。

答案 1 :(得分:1)

实际上,System.out.println已同步。如果没有这些,请再试一次。

答案 2 :(得分:1)

每个线程都有自己的StringBuilder,BufferedReader和FileReader(以及操作系统级文件描述符),因此在该级别不会有任何干扰。 (这些类都不是线程安全的,但实例是线程限制的,因此无关紧要。)

在您编写时,PrintWriter.print(...)PrintWriter.println(...)方法会同步,这就解释了为什么您没有看到混合在一起的各个println调用的输出。 (PrintWriter是线程安全的...并且需要。)

注意:如果您更改了代码以在每个println'ed字符串中包含线程编号,那么可能偶尔会看到输出以意外顺序出现。对同一对象(PrintWriter)的线程安全方法的单独调用不一定以“先到先得”的顺序发生。


更新静态变量i的代码不是线程安全的,并且可能偶尔会给你意想不到的(不正确的)结果......取决于你使用的硬件/ JVM。您应该使用synchronized static方法进行更新,或将i替换为AtomicInteger

答案 3 :(得分:0)

bufferreader和stringbuilder不在线程之间共享,因此它们的使用是线程安全的。

StringBuffer在某种程度上是线程安全的,因为它的所有方法都是同步的。 BufferedReader不是线程安全的。

答案 4 :(得分:0)

局部变量线程受限。但静态变量i++上的非原子操作(如i)不是线程安全的。