Java面试问题——线程全面详解总结

Wesley13
• 阅读 587

一、多线程是什么?为什么要用多线程?

介绍多线程之前要介绍线程,介绍线程则离不开进程。

首先进程 :是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元;

线程:就是进程中的一个独立控制单元,线程在控制着进程的执行。一个进程中至少有一个进程。

多线程:一个进程中不只有一个线程。

为什么要用多线程:

  • 为了更好的利用cpu的资源,如果只有一个线程,则第二个任务必须等到第一个任务结束后才能进行,如果使用多线程则在主线程执行任务的同时可以执行其他任务,而不需要等待;
  • 进程之间不能共享数据,线程可以;
  • 系统创建进程需要为该进程重新分配系统资源,创建线程代价比较小;
  • Java语言内置了多线程功能支持,简化了java多线程编程。

二、线程的生命周期:

新建 :从新建一个线程对象到程序start() 这个线程之间的状态,都是新建状态;

就绪 :线程对象调用start()方法后,就处于就绪状态,等到JVM里的线程调度器的调度;

运行 :就绪状态下的线程在获取CPU资源后就可以执行run(),此时的线程便处于运行状态,运行状态的线程可变为就绪、阻塞及死亡三种状态。

等待/阻塞/睡眠 :在一个线程执行了sleep(睡眠)、suspend(挂起)等方法后会失去所占有的资源,从而进入阻塞状态,在睡眠结束后可重新进入就绪状态。

终止 :run()方法完成后或发生其他终止条件时就会切换到终止状态。

三、创建线程的方法(还有其他方法):

1、继承Thread类:

步骤: 、定义类继承Thread;

  • 复写Thread类中的run方法;

目的:将自定义代码存储在run方法,让线程运行

  • 调用线程的start方法:

该方法有两步:启动线程,调用run方法。

2、实现Runnable接口:接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参方法。

实现步骤: 、定义类实现Runnable接口

  • 覆盖Runnable接口中的run方法
    将线程要运行的代码放在该run方法中。
  • 通过Thread类建立线程对象。
  • 将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
    自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程执行指定对象的run方法就要先明确run方法所属对象
  • 调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

3、通过Callable和Future创建线程:

实现步骤:

  • 创建Callable接口的实现类,并实现call()方法,改方法将作为线程执行体,且具有返回值。
  • 创建Callable实现类的实例,使用FutrueTask类进行包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值
  • 使用FutureTask对象作为Thread对象启动新线程。
  • 调用FutureTask对象的get()方法获取子线程执行结束后的返回值。

四、继承Thread类和实现Runnable接口、实现Callable接口的区别。

继承Thread:线程代码存放在Thread子类run方法中。

  • 优势:编写简单,可直接用this.getname()获取当前线程,不必使用Thread.currentThread()方法。
  • 劣势:已经继承了Thread类,无法再继承其他类。

实现Runnable:线程代码存放在接口的子类的run方法中。

  • 优势:避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
  • 劣势:比较复杂、访问线程必须使用Thread.currentThread()方法、无返回值。

实现Callable:

  • 优势:有返回值、避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
  • 劣势:比较复杂、访问线程必须使用Thread.currentThread()方法建议使用实现接口的方式创建多线程。

五、线程状态管理

1、线程睡眠---sleep:

线程睡眠的原因:线程执行的太快,或需要强制执行到下一个线程。

线程睡眠的方法(两个):sleep(long millis)在指定的毫秒数内让正在执行的线程休眠。

sleep(long millis,int nanos)在指定的毫秒数加指定的纳秒数内让正在执行的线程休眠。

线程睡眠的代码演示:

public class SynTest {
    public static void main(String[] args) {
        new Thread(new CountDown(),"倒计时").start();
    }
}
class CountDown implements Runnable{
    int time = 10;
    public void run() {
        while (true) {
            if(time>=0){
                System.out.println(Thread.currentThread().getName() + ":" + time--);
                try {
                    Thread.sleep(1000);
                    //睡眠时间为1秒
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

每隔一秒则会打印一次,打印结果为:

倒计时:10
倒计时:9
倒计时:8
倒计时:7
倒计时:6
倒计时:5
倒计时:4
倒计时:3
倒计时:2
倒计时:1
倒计时:0

扩展:

Java线程调度是Java多线程的核心,只有良好的调度,才能充分发挥系统的性能,提高程序的执行效率。但是不管程序员怎么编写调度,只能最大限度的影响线程执行的次序,而不能做到精准控制。因为使用sleep方法之后,线程是进入阻塞状态的,只有当睡眠的时间结束,才会重新进入到就绪状态,而就绪状态进入到运行状态,是由系统控制的,我们不可能精准的去干涉它,所以如果调用Thread.sleep(1000)使得线程睡眠1秒,可能结果会大于1秒。

总结

同步的前提:

  1. 必须要有两个或者两个以上的线程。
  2. 必须是多个线程使用同一个锁。
  3. 必须保证同步中只能有一个线程在运行。
  4. 只能同步方法,不能同步变量和类。
  5. 不必同步类中所有方法,类可以拥有同步和非同步的方法。
  6. 如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。
  7. 线程睡眠时,它所持的任何锁都不会释放。
    • 好处:解决了多线程的安全问题。
    • 弊端:多个线程需要判断,消耗资源,降低效率。

如何找问题?

  1. 明确哪些代码是多线程运行代码。
  2. 明确共享数据。
  3. 明确多线程运行代码中哪些语句是操作共享数据的。

写在最后

 Java面试问题——线程全面详解总结

  • 第一:看完点赞,感谢您对作者的认可;
  • ...
  • 第二:随手转发,分享知识,让更多人学习到;
  • ...
  • 第三:记得点关注,每天更新的!!!
  • ...
点赞
收藏
评论区
推荐文章
半臻 半臻
3年前
Python基础10——线程、进程、协程
18线程18.1进程和线程进程:打开一个程序至少就会有一个进程。操作系统进行资源分配的基本单位线程:线程是CPU调度的基本单位,每个进程至少都有一个线程。单线程:只有一个线程pythondeffuna():print(123)deffunb():print(456)funa()funb()先执行funa再执行funb多线程线程
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
DevOpSec DevOpSec
3年前
python多线程原理和详解(一)
python多线程原理和详解线程概念1.线程是什么?线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
Wesley13 Wesley13
3年前
java多线程的3种实现方式
多线程相关的问题1.什么是进程?​正在执行的程序2.什么是线程?​进程的子单位,一个能够完成独立功能的执行路径3.为什么需要开启多线程?当执行某些耗时操作的任务的时候需要开启多线程,防止线程阻塞能够让两个任务看起来像是在同时执行
Wesley13 Wesley13
3年前
java多线程大汇总,线程与进程,线程调度,并发与并行,创建线程方式,线程生命周期,线程安全,线程通信,线程池
1.线程与进程进程是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间线程1、是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行.一个进程最少有一个线程2、线程实际上是在进程基础之上的进一步划分,一个进程启动之后,里面的若干执行路径又可以划分成若干个线程
Wesley13 Wesley13
3年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Wesley13 Wesley13
3年前
Java并发基础
一、多线程基础知识1.进程和线程进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。线程:进程内部的一个独立执行单元;一个进程可以同时并发的运行多个线程,
Wesley13 Wesley13
3年前
Java高级教程02
\TOC\1.Java线程1.1.多线程和多进程多进程:操作系统能够同时进行多个任务:每个app(word,播放器,浏览器)可以同时运行多线程:同一应用程序中哟多个顺序流同时执行线程是进程中的一部分1.2.线程的执行过程:!(
Wesley13 Wesley13
3年前
Java总结:Java多线程
多线程作为Java中很重要的一个知识点,在此还是有必要总结一下的。Java给多线程编程提供了内置的支持。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。这里定义和线程相关的另一个术语进程:一个进程包括由操作系统分配的内存空间,
Wesley13 Wesley13
3年前
Java面试官都爱问的多线程和并发面试题汇总,多刷一题,多份安心!
Java多线程面试问题1、进程和线程之间有什么不同?一个进程是一个独立(selfcontained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的资源来创建和驻留在进