zoukankan      html  css  js  c++  java
  • java线程的小问题与回答

    问题1.进程与线程的关系

    进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。
    线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
    简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程

    问题2.多线程两种实现方式

    ①创建线程方式一继承Thread类
    创建线程的步骤:
    1 定义一个类继承Thread。
    2 重写run方法。
    3 创建子类对象,就是创建线程对象。
    4 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。

    ②创建线程方式—实现Runnable接口
    1、定义类实现Runnable接口。
    2、覆盖接口中的run方法。。
    3、创建Thread类的对象
    4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
    5、调用Thread类的start方法开启线程。

    思考:线程对象调用 run方法和调用start方法区别?
    线程对象调用run方法不开启线程。仅是对象调用方法。线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行

    思考:我们为什么要继承Thread类,并调用其的start方法才能开启线程呢?
    继承Thread类:因为Thread类用来描述线程,具备线程应该有功能。那为什么不直接创建Thread类的对象呢?如下代码:

    Thread t1 = new Thread();
    t1.start();//这样做没有错,但是该start调用的是Thread类中的run方法,而这个run方法没有做什么事情,更重要的是这个run方法中并没有定义我们需要让线程执行的代码。
    

    问题3.多线程两种实现方式的区别

    ---- 为什么需要定一个类去实现Runnable接口呢?继承Thread类和实现Runnable接口有啥区别呢?
    **实现Runnable接口,避免了继承Thread类的单继承局限性(你不能让我的类只继承而不继承别的类吧)。覆盖Runnable接口中的run方法,将线程任务代码定义到run方法中。
    创建Thread类的对象,只有创建Thread类的对象才可以创建线程。线程任务已被封装到Runnable接口的run方法中,而这个run方法所属于Runnable接口的子类对象,所以将这个子类对象作为参数传递给Thread的构造函数,这样,线程对象创建时就可以明确要运行的线程的任务。
    **

    问题4.线程池的原理

    线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象(既new Thread();)的操作,无需反复创建线程而消耗过多资源。

    ------详细的解释一下为什么要使用线程池?
    在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,创建和销毁线程花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务。
    线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。

    问题5.线程的生命周期

    ① 新建状态(New Thread) :在Java语言中使用new 操作符创建一个线程后,该线程仅仅是一个空对象,它具备类线程的一些特征,但此时系统没有为其分配资源,这时的线程处于创建状态。
    线程处于创建状态时,可通过Thread类的方法来设置各种属性,如线程的优先级(setPriority)、线程名(setName)和线程的类型(setDaemon)等。

    ②就绪状态(Runnable):使用start()方法启动一个线程后,系统为该线程分配了除CPU外的所需资源,使该线程处于就绪状态。
    ③ 运行状态(Running):Java运行系统通过调度选中一个处于就绪状态的线程,使其占有CPU并转为运行状态。此时,系统真正执行线程的run()方法。
    ④ 阻塞和唤醒线程
    阻塞状态(Blocked):一个正在运行的线程因某些原因不能继续运行时,就进入阻塞 状态。这些原因包括:

    (a) 当执行了某个线程对象的sleep()等阻塞类型的方法时,该线程对象会被置入一个阻塞集内,等待超时而自动苏醒。

    (b) 当多个线程试图进入某个同步区域时,没能进入该同步区域的线程会被置入锁定集,直到获得该同步区域的锁,进入就绪状态。

    (c) 当线程执行了某个对象的wait()方法时,线程会被置入该对象的等待集中,知道执行了该对象的notify()方法wait()/notify()方法的执行要求线程首先获得该对象的锁。

    ⑤ 死亡状态(Dead):线程在run()方法执行结束后进入死亡状态。此外,如果线程执行了interrupt()或stop()方法,那么它也会以异常退出的方式进入死亡状态。

    问题6.wait和sleep的区别

    sleep: 不释放锁对象, 释放CPU使用权
    在休眠的时间内,不能唤醒
    wait(): 释放锁对象, 释放CPU使用权
    在等待的时间内,能唤醒

    问题7.线程的生命周期(五中状态的切换流程)

    问题8.为什么wait(),notify(),notifyAll()等方法都定义在Object类中

    锁对象可以是任意类型的对象
    

    另外:同步锁 多个线程想保证线程安全,必须要使用同一个锁对象

    问题9.启动一个线程是run()还是start()?它们的区别?

    启动一个线程是start()
    区别:
    	start: 启动线程,并调用线程中的run()方法
    	run  : 执行该线程对象要执行的任务
    

    问题10.多线程有几种实现方案,分别是哪几种?

    a, 继承Thread类
    b, 实现Runnable接口
    c, 通过线程池,实现Callable接口
    

    问题11.同步有几种方式,分别是什么?

    a,同步代码块
    b,同步方法
      静态同步方法
    

    问题12 为什么wait(), notify(), notifyAll()这些操作线程的方法定义在Object类中?

    因为这些方法在使用时,必须要标明所属的锁,而锁又可以是任意对象。能被任意对象调用的方法一定定义在Object类中。

    笔记

    等待唤醒机制所涉及到的方法:
     wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。
     notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。
     notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。
    其实,所谓唤醒的意思就是让 线程池中的线程具备执行资格。必须注意的是,这些方法都是在 同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。

  • 相关阅读:
    [CodeIgniter4]-将控制器放入子目录中
    [CodeIgniter4]-控制器
    [CodeIgniter4]-处理多环境
    [CodeIgniter4]-管理多个应用
    [CodeIgniter4]-代码模块
    [CodeIgniter4]-网页缓存
    [CodeIgniter4]-错误处理
    netfilter分析
    使用 SELinux 和 Smack 增强轻量级容器
    如何增强 Linux 系统的安全性,第一部分: Linux 安全模块(LSM)简介
  • 原文地址:https://www.cnblogs.com/czy16/p/8321981.html
Copyright © 2011-2022 走看看