六、线程间通信问题(线程中常用的方法)

线程间通信

思考1:wait()、notify()、notifyAll()用来操作线程为什么定义在Object类中?
1.这些方法存在于同步中
2.使用这些方法时必须要标识所属的锁
3.锁可以是任意对象,所以任意对象调用的方法一定定义Object类中
思考2:wait()、sleep()有什么区别?
Wait():释放资源、释放锁
Sleep():释放资源,不释放锁

线程间通讯:

其实就是多个线程在操作同一个资源
但是操作的动作不同

等待唤醒机制

锁.wait()和锁.notify()、锁.notifyAll()共用
wait
notify
notifyAll
都使用在同步中,因为要对持有监视器(锁)的线程操作
所以要使用在同步中,因为只有同步才具有锁

为什么这些操作线程的方式要定义在Object类中呢?

因为这些方法在操作同步中线城市,都必须标识它们所操作线程持有的锁
只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒

也就是说,等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中

生产者和消费者问题

对于多个生产者和消费者
为什么要定义while判断标记
原因:让被唤醒的线程再一次判断标记

为什么是natifyAll()

因为要唤醒对方线程
因为只用notify:容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待

JDK1.5提供了多线程升级解决方案

JDK1.5后 显式的锁机制以及显式的锁对象等待唤醒机制

将同步Synchronized替换成现实Lock操作
将Object中的wait、notify、notfityAll替换成了Condition对象
该对象可以Lock锁获取
实现了本方只唤醒对方操作

接口 Lock

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。
所有已知实现类:

ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock 

六、线程间通信问题(线程中常用的方法)_第1张图片

接口 Condition

Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
六、线程间通信问题(线程中常用的方法)_第2张图片

private Lock lock=new ReentrantLock();//
private Condition condition1=lock.newCondition();
private Condition condition2=lock.newCondition();
lock.lock();//获取锁
Condition1.await();//造成当前线程在接到信号或被中断之前一直处于等待状态
Condition2.signal();//唤醒一个等待线程 唤醒对方 signalAll()
Finally{
lock.unlock();//释放锁的操作一定要执行
}

停止线程

1.定义循环结束标记
因为线程代码一定都是循环,只要控制了循环即可
3.使用interrupt(中断)方法
该方法是结束线程的冻结状态,使线程回到运行状态中来
注:stop方法已经过时,不再使用

stop方法已经过时

如何停止线程?

只有一种,run方法结束
开启多线程运行,运行代码通常是循环结构

只要控制住循环,就可以让润方法结束,也就是线程结束

特殊情况:

当线程处于冻结状态
就不会读取到标记,那么线程就不会结束

当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除
强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束

Thread类提供了该方法 interrupt();

Interrupt //处理sleep和 wait 让它们强制性到运行状态
中断线程。 如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的 checkAccess 方法就会被调用,这可能抛出 SecurityException。
如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。

setDaemon() //守护线程,后台线程

将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
该方法必须在启动线程前调用。

t1.setDaemon();
t1.start();

Join() //抢夺CPU执行权

等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

t1.start();
t1.join();

Join()
当A线程执行到B线程的join()方法时候,A就会等待,等B线程都执行完,A才会执行
join可以用来临时加入线程执行

setPriority()

更改线程的优先级。
六、线程间通信问题(线程中常用的方法)_第3张图片

t1.start();
t1.setPriority(MAX_PRIORITY );

yield() //临时释放

暂停当前正在执行的线程对象,并执行其他线程。

你可能感兴趣的:(JAVA多线程)