Java多线程入门(一)——多线程基本概念

       Java多线程的知识现在是面试或笔试中经常会问的问题,主要是考察面试者对并发是否有所了解。当然这一系列Java多线程只是入门,并不涉及到很深入的并发编程知识。我们在学习Java多线程之前需要先了解以下几个概念。

1、程序、进程、线程、多线程

  ①、程序(program)

       程序这个词现在应该无人不知,无人不晓,因为大家每天都在使用程序。但是如果你在面试的时候,别人问你一句:你知道什么是程序吗?如果程序是什么都不知道还敢说自己是一名程序员。

       程序:就是为了完成特定的任务,用某种语言编写的一系列指令的集合。即一组计算机能识别和执行的静态代码,静态对象。

  ②、进程(process)

       进程:是指一个内存中运行的应用程序。每个进程都有自己独立的一块内存空间,进程是一个动态的过程,它自身伴随着程序启动,运行,关闭的整个生命周期过程。比如在Windows系统中运行的QQ,Google Chrome等。

       我们可在电脑屏幕底部的任务栏,右键打开任务管理器查看当前任务的进程和线程:

image

   ③、线程(thread)

       线程是一条执行路径,是进程中的一个执行流程,是CPU调度和分派的基本单位,一个进程可以由多个线程组成。比如下图的Google Chrome进程中运行的多个线程。线程总是属于某个进程,线程没有自己的虚拟地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。线程由CPU独立调度执行,在多核CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。

image

   ④、多线程

       多线程:指的是一个程序(一个进程)在运行时产生了不止一个线程,产生的多个线程同时运行或交替运行,如果是单核CPU(现在哪还有这种CPU呀),也是交替运行,只不过要等一个线程运行完后才能运行下一个线程,因为在一个单位时间内,CPU只能执行一个线程任务,其实它是一种假的多线程。如果是多核CPU,才能发挥出多线程真正的效率。例如上面的Google浏览器就产生了很多个线程。

       多线程的作用一句话来说明:为了提高程序的效率(注意不是提高运行速度,宽带速度)。

2、并行与并发

    并行:是指同一时刻内CPU处理了两个或多个任务,是真正的同时。例如多个人同时做不同的事。

    并发:是指同一时间间隔内CPU执行了两个或多个任务。例如抢红包,秒杀商品,多个人做同一件的事。

image

    由此可见:并行是针对进程的,并发是针对线程的。

    所以在多线程编程实践中,一般都称多线程并发编程而不是多线程并行编程。

3、进程和线程的区别

   进程:

  • 进程可以产生多个线程,但至少有一个线程。
  • 进程作为资源分配的单位,系统在运行时会为每个进程分配独立的内存空间。所以进程中的数据存放空间是独立的(堆空间和方法区内存)。

   线程:

  • 线程总是属于某个进程。线程消耗的资源比进程小的多。
  • 线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(PC)。
  • 同一个进程中的线程共享其它进程中的内存和资源。因为堆内存和方法区内存是共享的,而栈内存是独立的不共享,每个线程有自己独立的栈。

image

这样虽然使得线程的通信更加简单、高效,但是当一进程中的多个线程同时访问相同的资源时就可能会带来安全隐患。出现数据不一致的现象,此时需要使用到后面讲到的同步机制。

由于创建一个线程的开销比创建一个进程的开销小的多,那么我们在开发多任务运行的时候,通常考虑创建多线程,而不是创建多进程。

4、使用多线程的优点

  1. 提高程序的响应,增加用户的体验。
  2. 最大限度的利用CPU的空闲时间来处理其他任务。
  3. 提高程序的效率。注意:它不是提高运行速度,而是提高CPU的使用率,从而使程序的运行效率加快了。
  4. 系统创建进程需要为该进程重新分配系统资源,创建线程的代价则小的多,因此多任务并发时,多线程效率高。

5、Java中的主线程

       在运行的Java程序中至少包含了两个线程,一个主线程是main()方法线程,另外一个是垃圾回收机制线程。每当使用Java命令执行一个类时,都会启动一个JVM,并且加载对应的class文件,而每一个JVM在操作系统中启动了一个main()方法的主线程,Java 本身具备了垃圾的收集机制,所以在 Java 运行时至少会启动两个线程。当代码执行时,JVM会从main方法开始执行我们的程序代码,一直把main方法的代码执行结束。如果在执行过程遇到循环时间比较长的代码,那么在循环之后的其他代码是不会被马上执行的。如下代码演示:

package com.thr;

/**
 * @author Administrator
 * @date 2020-03-12
 * @desc Java主线程
 */
public class Demo {
    //调用main方法,启动主线程
    public static void main(String[] args) {
        new Person("张三").show();
        new Person("李四").show();
        new Person("王五").show();
    }
}

class Person{
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void show(){
        for (int i = 0; i < 100000; i++) {
            System.out.println("name="+name+",i="+i);
        }
    }
}

在上述代码中show()方法中的循环执行次数很多,这时 匿名对象.show();下面的代码是依次按顺序从上往下执行,并且在输出窗口也可以看到按顺序不停的输出 name=XXX,i=值 这样的语句。那为什么会这样呢?原因是:JVM启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束为止,这个线程在Java中称之为主线程。当程序的主线程执行时,如果遇到了循环而导致程序在指定位置停留时间过长,则无法马上执行下面的程序,需要等待循环结束后能够执行。

那么,能否实现一个主线程负责执行其中一个循环,再由另一个线程负责其他代码的执行,最终实现多部分代码同时执行的效果?是能够实现同时执行,通过Java中的多线程技术来解决该问题。

原文地址:https://www.cnblogs.com/tanghaorong/p/12461727.html