线程等待、唤醒、实现相关

29 阅读3分钟

1.Java如何实现多线程之间的通讯和协作?

中断 和 共享变量。

2.notify()和notifyAll()有什么区别?

当一个线程进入wait之后,就必须等其他线程notify/notifyall,使用Notifyall可以唤醒所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一个。

如果没有把握,建议notifyAll,防止notigy因为信号丢失而造成程序异常。

3.如何停止一个正在运行的线程?

使用共享变量的方式:

在这种方式中,之所以引用共享变量,是因为该变量可以被多个执行相同任务的线程用来作为是否中断的信号,通知中断线程执行。

使用interrupt方法终止线程

如果一个线程由于等待某些事件的发生而被阻塞,又该怎么阻止该线程呢?这种情况经常发生,比如当一个线程由于需要等候键盘输入而被阻塞,或者调用Thread.join()方法,或者Thread.sleep()方法,在网络中调用ServerSocket.accept()方法,或者调用了DatagramSocket.receive()方法时,都可能导致线程阻塞,使线程处于不可运行状态时,即使主线程中该线程的共享变量设置为true,但该线程此时根本无法检查循环标志,当然也就无法立即中断。

这里的建议是,不用使用stop()方法,而是使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻断状态,退出堵塞代码。

4.Java中有几种方法可以实现一个线程?

三种方式:

a.继承Thread 类

b.实现Runnable 接口

c.实现Callable接口,需要实现的是call()方法

5.Java中怎么唤醒一个阻塞的线程?

在Java发展史上曾经使用suspend()、resume()方法对于线程阻塞进行唤醒,但是随着出现很多问题,比较典型的还是死锁问题。解决方案可以使用以对象为目标的阻塞,即利用Object类的wait()和notify()方法实现线程阻塞。

首先,wait、notify方法是针对对象的,调用任意对象的wait()方法都将导致线程阻塞,阻塞的同时也将释放该对象的锁,相应地,调用任意对象的notify()方法则将随机解除该对象阻塞的线程,但它需要重新获取该对象的锁,直到获取成功才往下执行;

其次,wait、notify方法必须在synchronized块或方法中被调用,并且要保证同步块或方法的锁对象与调用wait、notify 方法的对象是同一个,如此一来在调用wait阻塞后当前线程就将之前获取的对象锁释放。

6.为什么调用start()方法时会执行run方法,能否直接调用run()方法?

当调用start()方法时将创建新的线程,并且执行在run()方法里面的代码。但是如果你直接调用run()方法,它不会创建新的线程也不会执行调用线程的代码,只会把run方法当做普通方法去执行。

7.什么是竞争条件?怎么发现和解决竞争?

当多个进程都企图对共享数据进行某种处理,而最后的结果又取决于进程运行的顺序时,则我们认为这发生了竞争条件(race condition)。