多线程

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)死锁产生的原因?

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

 

posted @ 2018-07-25 17:03  少说点话  阅读(157)  评论(0编辑  收藏  举报
网站运行: