黑马程序员——Java基础——多线程(二)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

5、Lock锁机制

但是,我们出现等待的情况时,我们只想唤醒对方线程,该怎么做呢?

Jdk升级后,这个问题得到解决

查阅api文档,工具类中有一个java.util.contcurrent.locks的包。包里面,有一些常用的接口和类

其中,有一个接口叫做Lock

   Lock 实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作。

使用synchronized是隐式的,而lock成为显式的。

Interface condition 是将object监视器方法(wait notify  notifyAll)分解成截然不同的对象。以便通过将这些对象与任意lock实现组合使用,为每个对象提供多个等待set

其中,lock替代了synchronizedcondition替代了object对象监视器方法的使用

我们用lockcondition来替代下这个程序:

   黑马程序员——Java基础——多线程(二)_第1张图片

黑马程序员——Java基础——多线程(二)_第2张图片 

 

但是,发现,我们现在做的只仅仅是替代了原来的代码。

signalAll()唤醒的是所有线程,包括本方线程,并不是仅仅是对方线程。

查阅api——Lock,我们发现,一个锁上可以有多个相关的condition对象。

我们可以创建两个condition对象,让他们分别代表生产者和消费者

黑马程序员——Java基础——多线程(二)_第3张图片 

Jdk1.5.0中提供了多线程升级解决方案

将同步synchronized替换成了显示的lock操作。

object中的waitnotifynotifyAll,替换了condition对象。

该对象可以通过lock.newCondition来创建。

在该示例中,实现了本方只唤醒对方的操作

Synchronizedlock机制的区别“

synchronized机制中,一个锁只对应一个waitnotify方法

lock机制中,一个锁可以对应多个condition对象,也就是对应多个waitnotify方法

一定程度避免死锁。

记住:释放锁的动作,一定要执行

6、停止线程

    1)停止线程的原理

    我们知道,线程里面一般都要写循环。那么如何让线程停止,我们需要再了解一下。

我们需要查阅api文档中关于thread类中的方法。有一个stop方法,但是已经过时。虚拟机不再识别了。

不再使用的原因,是它里面会有一些bug:不管什么原因,就使线程挂掉。

还有suspend方法,也是一样,这方法一运行,会发生死锁。

那么,没有了stop方法,我们咋让线程停止呢?

我们需要先了解下线程停止的原理:就是要让run方法结束。

 原理:

开启多线程运行,运行代码通常是循环结构

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

代码

.黑马程序员——Java基础——多线程(二)_第4张图片

黑马程序员——Java基础——多线程(二)_第5张图片 

原因:Main线程执行完了,改变了标记,但是,自定义的两个线程读到run方法内的wait()中,全部冻结了,这时,主线程已经执行完,那两个线程还不能活过来。就出现了上述结果。

特殊情况

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

发生这种特殊情况,我们可以强制结束

Thread类中为我们提供一个方法interrupt()中断线程。

注意:中断状态绝对不是停止线程。Stop方法才是停止线程。

Interrupt方法是强制清除线程的冻结状态,让线程恢复到运行状态中来。

黑马程序员——Java基础——多线程(二)_第6张图片 

黑马程序员——Java基础——多线程(二)_第7张图片 

 

0线程恢复到运行状态,处理异常后,又到while循环中判断,标记为真,又读到wait(),冻结了。

但是,只要线程能恢复,离结束就不远了。

黑马程序员——Java基础——多线程(二)_第8张图片 

 

3)总结:

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

B定义循环结束标记

   因为线程运行代码一般都是循环,只要控制了循环即可。

C使用interrupt(中断)方法。

   该方法是结束线程的冻结状态,使线程回到运行状态中来。

注:stop方法已经过时不再使用。

7、守护线程

         void setDaemon(boolean on)

将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,jvm退出。

该方法必须在启动线程前调用。

黑马程序员——Java基础——多线程(二)_第9张图片 

 

 

守护线程或者用户线程,其实就是后台线程。

当一个线程被标记为后台线程时,它将会与前台线程共同抢夺cpu资源。它开启运行都没有区别,只有结束有区别。

当所有前台线程都结束,后台线程会自动结束。

8、多线程中的join方法

    Public final void join() throws InterruptedException

等待该线程终止。

黑马程序员——Java基础——多线程(二)_第10张图片 

黑马程序员——Java基础——多线程(二)_第11张图片 

Join方法的应用

程序开发中,我们可以临时加入一个线程,这个线程运算完,另一个线程继续运算。

Join()特点:

A线程执行到了B线程的join方法时,线程就会等待,等B线程都执行完,a才会执行。

Join用来临时加入线程执行。

9、多线程优先级yield方法

  1)概念    

优先级:代表着抢夺资源的频率。

谁的优先级高,cpu就会多执行谁。

Thread类中的setPriority(int newPriority)更改线程的优先级。

所有线程包括主线程,优先级都是5.优先级一共10级。

2)一般设置三种

MAX_PRIORITY  10 最高优先级

MIN_PRIORITY   1  最低优先级 

NORM_PRIORITY  5  默认优先级

黑马程序员——Java基础——多线程(二)_第12张图片 

 

优先级最高,但并不代表,cpu不会执行别的线程。

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

11、线程应用

实际开发中,什么时候用多线程呢?

当程序中有多个循环,并且都相互独立,就可以用多线程,可以大大提高程序运行效率。

多用匿名内部类来实现线程创建。





------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------



你可能感兴趣的:(黑马程序员——Java基础——多线程(二))