Java面试老失利?必定是多线程面试答案有问题!

十一、下面的代码,实际上有几个线程在运行:编程

  

cfedc1a56ecb4ffeb5f7df0708bee65e.png

两个:线程t和main()方法(主线程)。安全

 

 

十二、线程的几种状态服务器

1.线程一般有五种状态,建立,就绪,运行、阻塞和死亡状态。多线程

2.阻塞的状况又分为三种:线程

  • (1)、等待阻塞:运行的线程执行wait()方法,该线程会释放占用的全部资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其余线程调用notify()或notifyAll()方法才能被唤醒,wait是object类的方法对象

  • (2)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。blog

  • (3)、其余阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程从新转入就绪状态。sleep是Thread类的方法生命周期

  •  

  • 1.新建状态(New):新建立了一个线程对象。资源

  • 2.就绪状态(Runnable):线程对象建立后,其余线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。同步

  • 3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

  • 4.阻塞状态(Blocked):阻塞状态是线程由于某种缘由放弃CPU使用权,暂时中止运行。直到线程进入就绪状态,才有机会转到运行状态。

  • 5.死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

 

 

1三、说说:sleep、yield、join、wait方法的区别。

sleep()方法须要指定等待的时间,它可让当前正在执行的线程在指定的时间内暂停执行,进入阻塞状态,该方法既可让其余同优先级或者高优先级的线程获得执行的机会,也可让低优先级的线程获得执行机会。可是sleep()方法不会释放“锁标志”,也就是说若是有synchronized同步块,其余线程仍然不能访问共享数据。 做用于线程

  • ·  Thread.sleep()方法用来暂停线程的执行,将CPU放给线程调度器。

  • ·  Thread.sleep()方法是一个静态方法,它暂停的是当前执行的线程。

  • ·  Java有两种sleep方法,一个只有一个毫秒参数,另外一个有毫秒和纳秒两个参数。

  • ·  与wait方法不一样,sleep方法不会释放锁

  • ·  若是其余的线程中断了一个休眠的线程,sleep方法会抛出Interrupted Exception。

  • ·  休眠的线程在唤醒以后不保证能获取到CPU,它会先进入就绪态,与其余线程竞争CPU。

  • ·  有一个易错的地方,当调用t.sleep()的时候,会暂停线程t。这是不对的,由于Thread.sleep是一个静态方法,它会使当前线程而不是线程t进入休眠状态。


join(): 当前线程等待调用此方法的线程执行结束再继续执行。如:在main方法中调用t.join(),那main方法在此时进入阻塞状态,一直等t线程执行完,main方法再恢复到就绪状态,准备继续执行。

join方法必须在线程start方法调用以后调用才有意义。这个也很容易理解:若是一个线程都没有start,那它也就没法同步了。做用于线程

 

实现原理

0d19868471f745498f84cb58e4e09629.png

yield(): 它仅仅释放线程所占有的CPU资源,从而让其余线程有机会运行,可是并不能保证某个特定的线程可以得到CPU资源。谁能得到CPU彻底取决于调度器,在有些状况下调用yield方法的线程甚至会再次获得CPU资源。因此,依赖于yield方法是不可靠的,它只能尽力而为。做用于线程

wait():

·       wait只能在同步(synchronize)环境中被调用,而sleep不须要。

·       进入wait状态的线程可以被notify和notifyAll线程唤醒,可是进入sleeping状态的线程不能被notify方法唤醒。

·       wait一般有条件地执行,线程会一直处于wait状态,直到某个条件变为真。可是sleep仅仅让你的线程进入睡眠状态。

·       wait方法在进入wait状态的时候会释放对象的锁,可是sleep方法不会。

wait方法是针对一个被同步代码块加锁的对象

8661a29c0b4a48faa98fa3b2f4707bb6.png

见代码ThreadBlockTest1-5

 

 

1四、为何不推荐使用stop和destroy方法来结束线程的运行?

stop():此方法能够强行停止一个正在运行或挂起的线程。但stop方法不安全,就像强行切断计算机电源,而不是按正常程序关机。可能会产生不可预料的结果。

举例来讲:

当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会当即中止,并抛出特殊的ThreadDeath()异常。这里的“当即”由于太“当即”了,

假如一个线程正在执行:

8438051010144d44adfdc80310dd87e3.png

因为方法是同步的,多个线程访问时总能保证x,y被同时赋值,而若是一个线程正在执行到x = 3;时,被调用了 stop()方法,即便在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,因此请忘记 线程的stop方法,之后咱们不再要说“中止线程”了。

 

destroy():该方法最初用于破坏该线程,但不做任何资源释放。它所保持的任何监视器都会保持锁定状态。不过,该方法决不会被实现。即便要实现,它也极有可能以 suspend() 方式被死锁。若是目标线程被破坏时保持一个保护关键系统资源的锁,则任何线程在任什么时候候都没法再次访问该资源。若是另外一个线程曾试图锁定该资源,则会出现死锁。

 

 

1五、写个代码说明,终止线程的典型方式。

(1)    当run()方法执行完后,线程就自动终止了。

(2)    但有些时候run()方法不会结束(如服务器端监听程序),或者其它须要用循环来处理的任务。在这种状况下,通常是将这些任务放在一个循环中,如while循环。若是想让循环永远运行下去,可使用while(true){……}来处理。但要想使while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并经过设置这个标志为true或false来控制while循环是否退出。

见代码ThreadEndTest

代码中定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值。

 

 

1六、A线程的优先级是10,B线程的优先级是1,那么当进行调度时必定会调用A吗?

不必定。线程优先级对于不一样的线程调度器可能有不一样的含义,可能并非用户直观的推测。

见代码ThreadPriorityTest

 

 

1七、synchronize修饰在方法前是什么意思?

一次只能有一个线程进入该方法,其余线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.

见代码SynchronizedTest1

 

 

1八、使用Timer和TimerTask实现定时执行,定时在天天下午17:00执行。

见代码TimerTest1-3

知识点简介:

(1)        Timer:定时器,其实是个线程,定时调度所拥有的TimerTasks。

(2)        TimerTask:一个拥有run方法的类,须要定时执行的代码放到run方法体内。 TimerTask通常是以匿名类的方式建立。

语法简介:

4060724e0a29480ea773cf8478541df7.png

用法简介:

//如下是几种调度task的方法:  

21952e04f3384ee4b8a682e8f958eb8b.png

// time为Date类型:在指定时间执行一次。  

6c4d910f8e024c3fbf43c0005d75df86.png

// firstTime为Date类型,period为long  

// 从firstTime时刻开始,每隔period毫秒执行一次。  

c3ad8c72283144f89626fc5dc5b97cc8.png

// delay 为long类型:从如今起过delay毫秒执行一次  

06d512246fa34a31af3cbbd548c2f71b.png

// delay为long,period为long:从如今起过delay毫秒之后,每隔period  

// 毫秒执行一次。 

   举例:

18cf602858bd45f4aec996e8d277f0f3.png

 

 

1九、wait方法被调用时,所在线程是否会释放所持有的锁资源? sleep方法呢?

wait:释放CPU,释放锁;

sleep:释放CPU,不释放锁。

 

 

20、wait、notify、notifyAll是在Thread类中定义的方法吗?做用分别是什么?

wait(),notify(),notifyAll()不属于Thread类,而是属于Object类,也就是说每一个对象都有wait(),notify(),notifyAll()的功能。

由于每一个对像都有锁,锁是每一个对像的基础,而wait(),notify(),notifyAll()都是跟锁有关的方法。

 

三个方法的做用分别是:

  • wait:致使当前线程等待,进入阻塞状态,直到其余线程调用此对象的 notify() 方法或 notifyAll() 方法。当前线程必须拥有此对象监视器(对象锁)。该线程释放对此监视器的全部权并等待,直到其余线程经过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。而后该线程将等到从新得到对监视器的全部权后才能继续执行.

  • notify:唤醒在此对象监视器(对象锁)上等待的单个线程。若是全部线程都在此对象上等待,则会选择唤醒其中一个线程。直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。此方法只应由做为此对象监视器的全部者的线程来调用.

    "当前线程必须拥有此对象监视器"与"此方法只应由做为此对象监视器的全部者的线程来调用"说明wait方法与    notify方法必须在同步块内执行,即synchronized(obj以内).

  • notifyAll: 唤醒在此对象监视器(对象锁)上等待的全部线程。

 

 

2一、notify是唤醒所在对象wait pool中的第一个线程吗?

不是。

调用 notify() 方法致使解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,咱们没法预料哪个线程将会被选择。

22ceb816a8f04a6a97784f9451cd0262.png

相关文章
相关标签/搜索