------- android培训、java培训、期待与您交流! ----------
day12
14、线程间通讯:其实就是多个线程在操作同一个资源,但是操作的动作不同。
15、wait、notify()、notifyAll()都使用在同步中,因为要对持有监视器(锁)的线程进行操作。只有同步才具有锁。
wait和sleep的区别:
wait: 释放cpu执行权,释放同步中锁。
sleep:释放cpu执行权,不释放同步中锁。
为什么这些操作线程的方法(wait、notify()、notifyAll())要定义在Object类中呢?
因为这些方法在操作同步中的线程时,都必须要标识它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法应该定义在Object类中。
19、对于多个生产者和消费者,为什么要定义while判断标记?
原因在于让被唤醒的线程再一次判断标记,否则会导致死锁。
为什么定义notifyAll()?
因为需要唤醒对方线程。若是只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。 参见ProducerConsumerDemo.java
JDK1.5 中提供了多线程升级的解决方案,提供了一些新的对象,优化了等待唤醒机制。
1,将synchronized 替换成了Lock接口。将隐式锁,升级成了显示锁。
Lock 获取锁:lock();
释放锁:unlock();注意:释放的动作一定要执行,所以通常定义在finally中。
获取Condition对象:newCondition();
2,将Object中的wait,notify,notifyAll方法都替换成了Condition的await,signal,signalAll。注意导入包:import java.util.concurrent.locks.*;
和以前不同是:一个同步代码块具备一个锁,该锁具备自己的独立wait和notify方法。现在是将wait,notify等方法封装进一个特有的对象Condition(换成了await(); signal(); signalAll();),而一个Lock锁上可以有多个Condition对象。例如:
private Lock lock = new ReentrantLock(); //Lock是个接口,需要被实现
//返回绑定到此 Lock 实例的新Condition实例
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
该示例中,实现了本方只唤醒对方操作。(参见ProducerConsumerDemo2.java)
20、stop方法已经过时。如何停止线程?
原理:run方法结束。run方法中通常定义循环,只要控制住循环线程即可结束。
做法:1,定义结束标记。
2,当线程处于冻结状态,没有执行标记,程序一样无法结束。这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt(),目的是让线程强制从冻结状态恢复到运行状态,但是会发生InterruptedException异常。
21、public final void setDaemon(boolean on):将线程标记为后台线程,后台线程和前台线程一样开启,一样抢执行权运行,只有在结束时有区别,当前台线程都运行结束后,后台线程会自动结束。该方法必须在启动线程前调用。
22、join:当A线程执行到了B线程的join()方法时,A就会等待。等B线程都执行完,A才会执行。join可以用来临时加入线程执行。
23、setPriority(int newPriority):更改线程的优先级。
yield():暂停当前正在执行的线程对象,并执行其他线程。
线程在项目设计中的应用,与内部类结合使用。参见ThreadTest.java。