爲什麼需要多線程
對於一些密集型的 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 去處理別的