进程:操作系统资源分配的最小单位
线程:操作系统调度的最小单位
多进程理解:一条流水线代表一个进程,要想提高效率,使用多进程,即增加多个流水线。
多线程理解:在一条流水线中增加多个工人,进而提高效率,但是一条流水线上的资源是有限的,即使用多线程也是有限制的。这里的资源指的是CPU资源,当线程达到一定数量后,将不会再增加效率。
1 进程与线程的区别:
- 进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)
- 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,而线程是共享进程中的数据、地址空间
- 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以 IPC(Inter-Process Communication,进程间通信)进行。
- 多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
2 使用多线程计算多个累加和
public class web {
static final int COUNT =10;
static final long NUMBER = 10000;
static long sum(){
long r=0;
for(long i=0;i<NUMBER;i++){
r+=i;
}
return r;
}
static void 单线程(){
long b = System.nanoTime();
for (int i = 0; i < COUNT; i++) {
System.out.println(sum());
}
long e = System.nanoTime();
double s = (e - b) / 1000_000_000.0;
System.out.printf("单线程,运行时间: %f%n", s);
}
//定义一个类,继承Thread,用来创建线程
//run()方法就是该线程要执行的任务
static class SumThread extends Thread{
@Override
public void run() {
System.out.println(sum());
}
}
static void 多线程() throws InterruptedException {
long b=System.nanoTime();
// 因为当前也处于一个线程中,所以,只需要再创建 COUNT - 1 个线程就够了
Thread[] threads = new Thread[COUNT-1];
for (int i=0;i<COUNT-1;i++){
// 创建的线程执行的就是上面定义的类中的 run 方法
threads[i] = new SumThread();
threads[i].start();
}
// 剩下的一次,当前线程来计算
System.out.println(sum());
//等待其他线程结束
for(int i=0;i<COUNT-1;i++){
threads[i].join();
}
long e = System.nanoTime();
double time = (e-b)/1000_000_000;
System.out.printf("多线程运行时间:%f%n",time);
}
public static void main(String[] args) throws InterruptedException {
单线程();
System.out.println("+++++++++++++++++++++++");
多线程();
}
}
首先要定义一个类,继承Thread,该类用来创建线程,其中,run()方法中的内容就是该线程要执行的任务。
static class SumThread extends Thread{
@Override
public void run() {
System.out.println(sum());
}
}
使用new SumThread()
创建一个线程,调用start()
方法启动该线程。join()
用来等待某线程结束。
for (int i=0;i<COUNT-1;i++){
// 创建的线程执行的就是上面定义的类中的 run 方法
threads[i] = new SumThread();
threads[i].start();
}
//等待其他线程结束
for(int i=0;i<COUNT-1;i++){
threads[i].join();
}
程序计时 nanoTime()返回的是纳秒nanoseconds:
* @return the current value of the running Java Virtual Machine's
* high-resolution time source, in nanoseconds
public static native long nanoTime();
注意:
- 除了创建的线程之外,创建线程的本身也属于一个线程。
- 当运算量较小时,反而多线程的运行时间要高于单线程。这是因为创建线程也是需要时间的。
3. 使用多线程解决IO阻塞问题
如果使用单线程进行读取用户输入时,用户操作时会发生阻塞。而多线程可以解决该问题。
public class test2 {
static int fib(int n){
if(n<2){
return 1;
}
return fib(n-1)+fib(n-2);
}
//定义一个使用线程的内部类
static class FibThread extends Thread{
int n;
FibThread(int n){
this.n=n;
}
@Override
public void run() {
System.out.printf("fib(%d) = %d%n",n,fib(n));
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入要计算的数: ");
int n = scanner.nextInt();
scanner.nextLine();
//System.out.println(fib(n));
new FibThread(n).start();
}
}
}
如果是单线程,当计算很大的数时,单线程会堵塞在计算fib(n)
这里,直到计算完成才继续向下执行,而使用多线程则完全没有这种问题。