初探多线程
2020-06-16 本文已影响0人
写代码的海怪
为什么需要多线程
对于一些密集型的 IO 操作如,网络 IO,文件 IO,我们很想当他们做 IO 操作的时候让 CPU 处理别的事情。这就需要多线程了。
因为 Java 一般是同步/阻塞的,所以多线程可以让我们做 A 的同时,去做 B。例如
// 声明线程
new Thread(Test::xxx).start();
new Thread(Test::xxx).start();
new Thread(Test::xxx).start();
xxx();
上面就是线程的简单用法。
start()
vs run()
这两个方法看上去很像,区别就是 start()
是到一边去做干活同时 CPU 干别的,而 run()
是干完活再干下一个。
作用域
- 局部变量是线程私有的
- 静态方法/类变量是被线程共享的
变量共享的问题
因为多线程的特点就是无序的,所以当用线程操作同一个东西的时候,有可能出现问题,如下面的例子:统计有多少个线程在工作
public class Test {
private static int count = 0;
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(Test::xxx).start();
}
}
private static void xxx() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
count += 1;
System.out.println("count: " + i);
}
}
结果就不对了

这里的原因是因为 i += 1
不是原子操作,操作分别如下:
- 先取 i 的值
- 把 i 的值 +1
- 把修改后的值写回 i
而线程又是无序的,所以上面3种状态都可能被不同线程访问到。
场景
- 对于 IO 密集型很好
- 网络 IO
- 文件 IO
- 不适合 CPU 密集
- 很有限
网络 IO,把数据一丢,CPU 去处理别的