'''
1. 线程导学上
'''
实现线程方法:
1>继承Thread
2>实现Runnable接口
Thread类也是Runnable接口子类,但Thread并没有重写Runnable中的run方法,故在使用Thread必须重写run。
另外,通过Thread并没有实现资源数据共享,而runnable可以进行资源共享。
线程同步
1>几个线程共享数据,但某时刻仅仅允许一个线程进行操作
2>生产者 消费者问题
一个线程负责将数据写入,另外一个线程负责将数据读出。二者并行
当数据区已满,则需要取出一部分数据才能继续写入,
当数据区已空,则需要生产一部分数据才能继续读出。
'''
2. 线程学习-中
'''
synchronize关键字
保证一段代码在多线程执行时是互斥的,
synchronize(t){};给t这个对象加锁,不允许其他线程调用
同步普通方法,锁的是当前对象。
同步静态方法,锁的是当前 Class 对象。
同步块,锁的是 {} 中的对象。
线程休眠不会释放锁
线程等待和唤醒
wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。
而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;
notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
if(){
try{wait()}catch{}};
notify();等待和唤醒,二者是相互依存的。
join()方法,让一个线程强制运行,在运行期间,其他线程无法运行。
yeild()方法,把资源让出来,供给同优先级别的其他线程运行。
后台线程:t.setDaemon(true)
它是在后台运行的,它的任务是为其他线程提供服务,这种线程被称为“后台线程(Daemon Thread)”,
又称为“守护线程”或“精灵线程”。JVM的垃圾回收线程就是典型的后台线程。
后台线程的特征:如果所有的前台线程都死亡了,后台线程也会自动死亡。
线程调度:
控制多个线程在一个CPU以某种顺序运行,称之为调度
每个线程赋予优先级为1-10,默认为5,setPriority()改变优先级。优先级高,先执行。
'''
3.线程学习-下
'''
数据共享:
不可变:在JAVA语言中,不可变对象一定是线程安全的。只要一个不可变对象被正确的构建出来(没有发生this逃逸的况),那其外部的可见状态永远也不会改变。保证对象行为不影响自己状态途径的途径有很多种,其中最简单的就是把对象中带有状态的变量都声明为final。
绝对线程安全:不管运行时环境如何环境如何,调用着都不要额外的同步措施。
线程相对安全:这个对象的单独的操作时线程安全的,但是对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证正确性。
线程兼容:指对象本生不是线程安全的,但是可以通过在调用端正确的使用同步手段来保证对象在并发环境中可以安全地使用。
线程对立:指无论调用端是否采取了同步措施,都无法在多线程环境中并发使用的代码。
线程安全实现方法:
互斥同步:指在多个线程并发访问共享数据时,保证共享数据在同一时刻只被一个(或者是一些)线程使用。Synchronize关键字是互斥同步最基本的手段。
非阻塞同步:基于冲突检测的乐观并发策略,也就是说,先进行操作,如果没有其他线程争用共享数据,按操作就成功了;如果共享数据有争用,产生了冲突,那就再采取其他的补偿措施,这种乐观的并发策略的许多实现都是不需要把线程挂起的。
ReentrantLock:(暂时不太懂)
ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁, 即当前线程获取该锁再次获取不会被阻塞。在java关键字synchronized隐式支持重入性(关于synchronized可以看这篇文章),synchronized通过获取自增, 释放自减的方式实现重入。与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。那么,要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:1. 重入性的实现原理;2. 公平锁和非公平锁。