对多线程有疑问。 以下是我访问文件的主程序,我在对象上创建了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
是线程安全的,或者因为每个线程都有自己的StringBuilder
和BufferedReader
副本?我可以看到内容被正确读取和写入。
答案 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
)不是线程安全的。