您的位置:首页 > 编程语言 > Java开发

好读书不求甚解(一)Java多线程编程核心技术

2016-10-08 23:22 411 查看
第1章 Java多线程技能

第2章 对象及变量的并发访问
1 synchronized同步方法

2 synchronized同步代码块

3 volatile

第3章 线程间通信
1 等待通知机制

2 join方法

3 ThreadLocal类

第4章 Lock的使用
1 ReentrantLock类

2 ReentrantReadWriteLock类

第5章 定时器Timer

第6章 单例模式与多线程

第7章 拾遗增补

内容总结

不好的地方

好的地方

看书经常看过后就没多少印象了,决定把看的做个简单记录或者摘要,用于加深印象.



第1章 Java多线程技能

1) 实现多线程变成的方式主要两种,一种是继承Thread类,一种是实现Runnable接口
2) currentThread()方法,返回代码段正在被哪个线程调用.要注意Thread.currentThread()和this的区别
3) isAlive()方法,判断当前线程是否处于活动状态.活动状态指线程已经启动且尚未终止
4) sleep()方法,当前正在执行的线程休眠指定时间,不释放锁
5) 停止线程的方法,正常停止(执行结束),stop方法(已废弃),interrupt方法
6) interrupted(),静态方法,测试当前线程是否已经中断,并清除中断标识
7) isInterrupted(),实例方法,测试线程是否已经中断,不清除中断标识
8) sleep的线程也可以停止(需要捕获异常)
9) yield()方法,让出CPU给其他线程,也可能让出后自己又抢到
10) 线程优先级,尽量不使用
11) 守护线程,java线程分两种,用户线程,守护线程.进程中没有用户线程后,守护线程自动销毁


第2章 对象及变量的并发访问

2.1 synchronized同步方法

1)方法内变量为线程安全(在栈上)
2)实例变量非线程安全(在堆上)
3)synchronized方法是锁定的实例对象,多个实例不互斥
4)锁可重入
5)出现异常,自动释放锁


2.2 synchronized同步代码块

1) 同步代码块通过减少同步的范围,来提高效率
2) synchronized() 参数如果不一个,则是异步
3) synchronized(class)锁定class对象=synchronized static方法
4) synchronized代码块尽量别用String作为锁对象


2.3 volatile

1) volatile修饰的变量具有可见性.即线程使用时都要从主内存读取.
2) volatile不具备原子性
3) 结合1,2两点, volatile适合只有一个线程修改数据,或者像一个线程修改flag=false,别的线程都停止这种.
4) 原子类也并不完全安全(方法间不同步),类似Hashtable


第3章 线程间通信

3.1 等待/通知机制

1) wait()方法使当前执行代码的线程进行等待.会立即释放锁
2) notify()方法通知呈wait状态且等待这个锁的线程,如果多个则随机通知一个.会释放锁,但不是立即,要等同步区域内代码执行完成
3) notifyAll()方法通知呈wait状态且等待这个锁的全部线程,释放锁和notify方法一样
4) 上面1,2,3都会释放锁,所以执行前都需要已经获得锁
5) sleep()方法不释放锁
6) wait()的线程,调用interrupt()方法会抛出InterruptedException
7) wait(long)是long时间内没有被唤醒的话,则自动被唤醒
8) 多生产者,多消费者 如果使用notify可能唤醒的是同类,可能出现假死情况.使用notifyAll来解决
9) 可以使用PipeInputStream,PipedOutputStream,PipedReader,PipedWriter实现线程间通信


3.2 join方法

1) join()的作用是使所属的线程对象x正常秩序run()中的任务,而使当前线程z阻塞到线程x销毁后再执行
2) join()是使用wait()方法实现的,synchronized是使用的"对象监视器"
3) 启动线程b,b中启动线程a,然后a.join(),如果b.interrupt(),则b抛出异常,a正常执行
4) join(long)比起join()多了个阻塞的时间,和sleep(long)的区别是join会释放锁(因为是用wait实现的)


3.3 ThreadLocal类

1) 各线程可以用ThreadLocal来存放私有数据.set()设置,get()返回(为什么不弄个map那样子的呢,呵呵)
2) get()的初始化值,可以通过extends ThreadLocal,override initialValue()实现


第4章 Lock的使用

4.1 ReentrantLock类

1) synchronized结合wait(),notify(),notifyAll()可以实现等待/通知模式,ReentrantLock借助Condition对象实现等待/通知模式
2) 使用notify()被通知的线程是JVM随机选的,Condition类可以自己选择
3) Object.wait()相当于Condition.await(),Object.notify()相当于 Condition.signal()
4) await()和signal()方法使用前需要获得锁
5) new ReentrantLock(boolean isFair) 可以指定是否为公平锁,不过公平锁也不是绝对公平的
6) 以下7-9是ReentrantLock类的一些方法说明
7) getHoldCount()返回调用lock()的次数,getQueueLength()返回正等待获取此锁的线程估计数,getWaitQueueLength(condition)返回正等待获取此锁此条件的线程估计数
8) hasQueuedTread(Thread thread)返回指定线程是否正在等待获取此锁,hasQueuedThreads()返回是否有线程正在等待获取此锁,hasWaiters(condition)返回是否有线程正在等待此锁此条件
9) isFair()返回是否公平锁,isHeldByCurrentThread()返回当前线程是否持有此锁,isLocked()返回此锁是否由任意线程持有


4.2 ReentrantReadWriteLock类

1) 读读共享,读写互斥,写写互斥,写读互斥


第5章 定时器Timer

书里只是讲了怎么使用,可以直接去看API文档,而且现在项目开发一般都使用封装过的spring task或者quartz,所以这里就不记录了


第6章 单例模式与多线程

1) 在博客 http://blog.csdn.net/qq315737546/article/details/29387381 中对单例模式有过说明
2) 最好使用枚举来实现单例,可以用class再包装一层(6.7的例子)


第7章 拾遗增补

1) Thread.State 枚举中,列出了线程的所有状态,并有解释




2) 线程状态通过有关方法进行切换,有些切换是单向的

3) 可以把线程归属到某一个线程组中,统一管理

4) SimpleDateFormat是非线程安全的

5) 线程异常可以通过UncaughtExceptionHandler进行捕获.可以setDefaultUcaughtExceptionHandler()设置默认的异常处理器

6) 默认情况下,线程组中一个线程出现异常不会影响其他线程,可以通过自定义线程组+重写uncaughtException()方法来停止组内所有线程

7) 线程异常处理 thread.setUncaughtExceptionHandler()>Thread.setDefaultUncaughtExceptionHandler()>线程组的异常处理

内容总结

1.  使用synchronized(同步方法,同步代码块),lock的时候,重点在于知道他们使用的对象监视器是否一个(即加锁的对象)
2.  lock比synchronized更强大,更灵活


不好的地方

1.  书里大部分例子都是用的XX extend Thread来实现, 这种实现可以直接调用XX实例xx.start()方法执行即可.不需要再Thread t = new Thread(xx), 我认为实现Runnable方式这样写更合适.(Thread类本身也实现了Runnable接口.....)
2.  有些地方有结论,有代码,但是没有说明,搞的有点不理解
3.  有些地方只有代码... 更难理解


好的地方

1.  代码示例很多,观点都通过代码去证明
2.  很多时候,对一些知识点不知道怎么去验证,这本书能加强举例子的能力
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 多线程