第一章 java 多线程技能
进程是操作系统的结构基础;是一次程序的执行。线程可以看成进程的一个子任务。线程可以通过继承Thread类或者实现runnable接口来实现。接口的实现优于继承。
停止线程可以通过抛异常,return;或者暴力手段stop();stop停止线程过于暴力,容易造成数据缺失,所以不建议
暂停线程suspend()和resume方法的使用
线程安全
通过synchronized同步方法实现
通过synchronize(监视器对象){}同步快来实现同步
脏读:线程在读取实例变量的时候,此值已经被其他线程更改了
当同步快出现异常时,锁自动释放
同步块可以有效的缩减同步的范围,缩短运行时间提高效率。
静态同步方法锁定的是Class类。静态同步方法对所有执行该方法是线程都是同步的
死锁的原因是
互斥条件。即某个资源在一段时间内只能由一个进程占有
不可抢占条件。进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源
占有且申请条件。进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞
循环等待条件。存在一个进程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一资源,以此类推
只要监视器对象没有改变,监视器对象的属性改变了,运行的结果还是同步的
valatile关键字
valatile主要保证了成员变量的一个可见性,主要运用场景是循环条件的关键字
valatile和synchronized的比较:
1、valatile是线程同步的轻量级实现,在性能上肯定要好于synchronized
2、多线程访问valitile不会发生阻塞,而synchronized会出现阻塞
3、valatile能保证数据的可见性,但是不能保证原子性,而synchronized 可以保证原子性,也可以间接保证可见性
4、valatile解决的是变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性
线程间通信
wait()使线程停止运行,而notify使停止的线程继续运行。
执行完wait()方法是立马释放锁 notify()执行完同步代码块才会释放锁,
在执行同步代码块过程遇到异常也会释放锁
通过字节流实现线程间通信
PipedInputStream 和 PipedOutputStream
PipedReader和PipedWriter
使用InputStream.connnect(OutputStream)使两个stream之间产生通信链接。
可以使用valatile修饰变量,用这个变量做开关实现交叉运行两段代码的目的。
join()方法释放当前线程的锁,sleep()占有锁不释放,
类Threadlocal解决的是变量在不同线程间的隔离性,也就是不同线程拥有自己的值,不同线程的值是可以 保存在Threadlocal进行保存
lock的使用
reentrantlock在功能上更加强大,比如具有嗅探功能,多路分支通知功能,使用上更加灵活
reentrantlock调用lock()加锁,一定要在finally{}模块中调用unlock()方法进行解锁
使用condition实现等待/通知:
可以调用condition await()方法和signal()方法来实现
可以通过在调用reentrantLock构造器的时候传入true和false来实现公平锁和非公平锁
使用condition实现顺序执行
使用多个condition,每个condition服务于一个线程。再使用个静态变量来控制唤醒指定的线程。
使用reentrantReadWriteLock可以加快运行效率,在某些不需要操作实例变量的方法中,完全可以使用读写锁来提升该方法的代码运行速度
定时器
Timer timer = new Timer()
timer schedule(task,dateRef):在指定时间运行任务
TimeTask是以队列的方式一个一个顺序执行的 所以执行的时间有可能和预期的时间不一致,因为前面的任务如果耗时较长,
后面的任务运行时间就会顺延。
timer schedule(task,datefirst,period)在指定时间以后周期性执行任务