zoukankan      html  css  js  c++  java
  • 多线程

    1)为什么要继承Thread类?

    在Java中使用Thread这个类对线程进行描述。而我们现在希望通过自己的代码操作线程,自己的代码应该需要和Thread类之间产生关系。这里我们采用的继承的关系。

    当我们继承了Thread类之后,我们自己的类也就变成了线程类。我们自己的类就继承到了Thread类中的所有功能,就具备了操作线程的各种方法,并且自己的类就可以对线程进行各种操作(开启线程等)。

    而我们自己定义的类称为了一个线程类,主要是因为可以复写run方法。

    2)为什么要复写run方法?

    为什么要使用线程:因为我们希望程序中的某段代码可以同时运行,提高程序的运行效率。

    我们定义的类继承了Thread类之后,其实在Thread类中有个run方法,它是开启线程之后,就会直接去运行的方法。而Java在设计线程类(Thread)的时候,就已经明确了线程应该执行的某段代码需要书写在run方法中,也就是说在run方法中的代码开启线程之后才能正常的运行。

    我们使用线程的目的是让线程执行后来自己程序中的某些代码, 而Java中规定需要线程执行的代码必须写run方法中,Thread类中的run方法中并没有我们真正需要多线程运行的代码,而开启线程又要去运行run方法,这时我们只能沿用Thread类run方法的定义格式,然后复写run方法的方法体代码。

      简单来讲:

             设计Thread这个API的人,在设计的时候,只设计了如何启动线程,至于线程要执行什么任务,他并不知道。所以,他这样设计:就是start启动线程之后,JVM会自动的调用run方法。

    因此,我们只要把自己的代码写到run方法中,就一定会被执行到。

    3)为什么要调用start而不是run?

    当书写了一个类继承了Thread类之后,这个子类也变成线程类。这时可以创建这个子类的对象,一旦创建Thread的子类对象,就相当于拥有了当前的线程对象。

    创建Thread的子类对象,只是在内存中有了线程这个对象,但是线程还不能真正的去运行。

    要让线程真正的在内存运行起来,必须调用start方法,因为start方法会先调用系统资源,启动线程。这样才能够在内存开启一片新的内存空间,然后负责当前线程需要执行的任务。

    我们直接通过线程对象去调用run方法,这时只是对象调用普通的方法,并没有调用系统资源,启动线程,也没有在内存中开启一个新的独立的内存空间运行任务代码。只有调用start方法才会开启一个独立的新的空间。并在新的空间中自动去运行run方法。

      注意:run方法仅仅是封装了线程的任务。它无法启动线程。

    面试题:start方法和run方法的区别?

             run:只是封装线程任务。

             start:先调用系统资源,在内存中开辟一个新的空间启动线程,再执行run方法。

    4)同一个线程对象是否可以多次启动线程?

    不能。如果同一个对象多次启动线程就会报如下异常。

    注意:如果想要启动多个线程,可以重新再创建一次自定义线程类的对象调用一次start()函数来启动线程。


    1)多线程有几种实现方案,分别是哪几种?

    两种:

             继承Thread:

                       A:自定义类,继承Thread

                       B:重写run方法

                       C:创建线程类对象

                       D:启动线程

             实现Runnable:

                       A:自定义类,实现Runnable接口

                       B:实现run方法

                       C:创建任务类对象

                       D:创建线程对象,把任务对象作为参数传递

                       E:启动线程

    2)同步有几种方式,分别是什么?

    三种:

             A:同步代码块:锁是任意对象,但是必须唯一

             B:同步方法:锁是this
             C:静态同步方法:锁是当前类的字节码文件对象。类名.class

    其实,在JDK1.5提供了新的同步机制:

             Lock

                       lock() 上锁

                       unlock() 释放锁

    3)run()函数和start()函数的区别?

             run :封装线程任务的

             start:先启动线程,再执行run方法

    4)sleep()和wait()方法的区别

    区别:

             A:sleep需要接收时间参数,wait不需要接收时间参数;

             B:sleep可以自然醒,wait必须等待别人唤醒;

             C:sleep不需要同步结合,wait必须与同步结合使用;

             D:sleep不释放锁,而wait会释放锁;

    联系:

             A:都会导致线程阻塞;

             B:都会释放CPU的执行资格和执行权;

    5)为什么wait(),notify(),notifyAll()等方法都定义在Object类中?

             首先:线程的通信必须由锁来控制

             然后,锁对象是任意的,任意对象都能调用的方法,必须定义在Object类中。     

    6)线程的生命周期图

                             阻塞(不可运行)

    创建 --->  就绪(可以运行) -->  运行(正在运行) -->死亡

    7)死锁产生的原因?

             在同步嵌套的情况下,如果多个线程争夺资源,就会出现死锁。

  • 相关阅读:
    Java并发--线程间协作的两种方式:wait、notify、notifyAll和Condition
    Java并发--Java线程面试题 Top 50
    Java并发--Timer和TimerTask
    Spring配置--Aop配置详情
    Spring配置--tx事务配置方式
    java并发--Callable、Future和FutureTask
    java并发--CountDownLatch、CyclicBarrier和Semaphore
    精通Matlab数字图像处理与识别
    油砂资源状况与储量评估方法
    家庭自制药蛋
  • 原文地址:https://www.cnblogs.com/sueyyyy/p/9366992.html
Copyright © 2011-2022 走看看