为什么需要多线程
- 所有的对象数据都在堆上面分配,变量只是一个指针而已
- Java的执行模型是同步/阻塞(block)的
- 发热量制约了电脑cpu赫兹的增长,只能堆核心
- 默认的main线程,默认就是一个线程

package com.github.hcsp.io;
 {
long t0 = System.currentTimeMillis();
slowFileOperation();
long t1 = System.currentTimeMillis();
System.out.println("耗时" + (t1 - t0) + "ms");
}
private static void slowFileOperation() {
try {
File tmp = File.createTempFile("tmp", "");
for (int i = 0; i< 10000; i++) {
try (FileOutputStream fos = new FileOutputStream(tmp)) {
fos.write(i);
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
线程最简单的方式
package com.github.hcsp.io;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
public class Crawler {
public static void main(String[] args) {
long t0 = System.currentTimeMillis();
new Thread(Crawler::slowFileOperation).start();
new Thread(Crawler::slowFileOperation).start();
new Thread(Crawler::slowFileOperation).start();
slowFileOperation();
long t1 = System.currentTimeMillis();
System.out.println("耗时" + (t1 - t0) + "ms");
}
private static void slowFileOperation() {
System.out.println("I am running");
try {
File tmp = File.createTempFile("tmp", "");
for (int i = 0; i< 10000; i++) {
try (FileOutputStream fos = new FileOutputStream(tmp)) {
fos.write(i);
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}


start方法才能开始执行并发
- start和run的区别,start才能并发执行,相当于雇佣一个工人,发给他一个说明书,run相当于等这个工人执行完了之后再去做下一件事情
- 每多开一个线程,就多一个执行流
- 方法栈是线程私有的

- 静态变量/类变量是被所有线程共享的
多线程共享资源是多线程各种坑的来源
package com.github.hcsp.io;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
public class Crawler {
public static int i = 0;
public static void main(String[] args) {
long t0 = System.currentTimeMillis();
new Thread(Crawler::slowFileOperation).start();
new Thread(Crawler::slowFileOperation).start();
new Thread(Crawler::slowFileOperation).start();
slowFileOperation();
long t1 = System.currentTimeMillis();
System.out.println("耗时" + (t1 - t0) + "ms");
}
private static void slowFileOperation() {
System.out.println("I am running");
i++;
System.out.println("I am i->" + i);
try {
File tmp = File.createTempFile("tmp", "");
for (int i = 0; i< 10000; i++) {
try (FileOutputStream fos = new FileOutputStream(tmp)) {
fos.write(i);
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
线程难的本质
package com.github.hcsp.io;
public class Crawler {
public static int i = 0;
public static void main(String[] args) {
long t0 = System.currentTimeMillis();
for (int j = 0; j < 1000; j++) {
new Thread(Crawler::modifySharedValues).start();
}
long t1 = System.currentTimeMillis();
System.out.println("耗时" + (t1 - t0) + "ms");
}
private static void modifySharedValues() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
System.out.println("i->" + i);
}
}
- 多个线程访问一个变量由于这个变量不是原子的,就有可能是正常有可能不正常

多线程带来的性能提升
- 对于IO密集型应用及其有用
- 对于CPU密集型应用稍有折扣
- 性能提升的上线在单核CPU100%,多核就是N*100%