http://www.cnblogs.com/chenshengjava/p/8604234.html
设计复杂
上下文切换开销大:
切换时限存储当前线程的本地数据、程序指针
载入另线程本地数据、指针
执行
安全:
同程序多线程不导致问题
多线程访问相同资源:
同一内存去(变量、数组、对象)系统(数据库、web service)或文件
对上述资源写操作有可能发生,资源没有改变、多线程读取安全
竞争同一资源,对资源访问顺序敏感(存在竞态条件)
导致竞态发生的代码区叫临界区
监控:
每个对象都有监视器、监视并发代码的重入,
非多线程编码时不起作用,在synchronized起
并行:多个cpu实例、多台机器同时执行一段处理逻辑
并发:cpu调度、看上去同时,公共资源
同步:通过人为控制和调度,保证对共享资源的多线程访问为线程安全、结果准确@synchronized
线程
安全:并发情况下代码多线程的调度顺序不影响结果,此时关心系统内存、cpu是否够用
不安全:线程调度顺序影响最终结果
多核:
线程从主存中读取值,复制到高速缓存中、操作、写入缓存、写入主存
并发:
原子性问题:
x++和 x = x+1包括3个操作:读取x的值,进行加1操作,写入新的值
synchronized和Lock能够保证任一时刻只有一个线程执行该代码块,无此问题
可见性问题:多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
被volatile修饰,保证修改的值会立即更新到主存,当有其他线程需要读取时,会去内存中读取新值
有序性:程序执行的顺序按照代码的先后顺序执行
指令重排:处理器 运行效率 代码优化 执行顺序变
volatile:
语义:不同线程对变量操作的可见性;2、禁止指令重排,一定程度上保证有序性;3、不原子性
volatile之前的语句再其执行之前一定先执行了,对后可见
https://blog.csdn.net/evankaka/article/details/51489322
线程池类:
4、newScheduledThreadPool计划线程池类,设置线程执行的先后间隔、时间
scheduleAtFixedRate:指定频率周期执行
scheduleWithFixedDelay:周期定时执行
线程池常用方法:
submit()适应生成消费者模式,future一块,有结果
execute()
shutdown()不再接收新的线程,所有线程执行完毕回收资源
shutdownNow()马上关闭线程池
进程:独立代码、数据空间,间切换开销大
线程:同一类线程共享代码和数据空间,每个线程有独立运行栈和程序计数器
多线程:同一程序多个顺序流在执行、乱序执行
多进程:操作系统同时运行多个任务
线程调度
调整优先级
static int MAX_PRIORITY
线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY
线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY
分配给线程的默认优先级,取值为5。
Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级。
每个线程都有默认的优先级。主线程的默认优先级为Thread.NORM_PRIORITY。
线程的优先级有继承关系,比如A线程中创建了B线程,那么B将和A具有相同的优先级。
线程睡眠:Thread.sleep(long millis)
设置睡眠时间,以毫秒为单位,结束转为就绪状态
等待:wait(),释放了锁
其他线程调其notify或notifyAll唤醒(==调用wait(0))
让步:yield,让给=<优先级的
加入:join,等待其他线程终
当前线程调用其他线程join,当前线程入阻塞、另一个进程结束、当前线程由阻塞转为就绪
子线程运行,主线程结束了
唤醒:nofity
interrupt:
中断是一个状态,方法将状态置为true
发送中断信号,在无限等待的线程抛错结束,
wait与notify需要与synchronized()一起使用,在其内
sleep和yield:
sleep指定时间内线程停滞、低级线程可执行
yield未知time内让出cpu占用权,低级没机会
wait,notify和notifyAll只能在同步控制方法或者同步控制块里
https://www.cnblogs.com/yjd_hycf_space/p/7526608.html 这个博客同步那块本宝有点懵
线程同步块:synchronized http://www.cnblogs.com/chenshengjava/p/8604234.html
同步块在Java中是同步在某个对象上
同步在一个对象上的同步块同时只能被一个线程进入并执行操作
其他等待进入该同步块的线程将被阻塞
作用域:不能继承
对象实例内,间不影响,内同时只有一个执行
类:synchronized static aStaticMethod{}防止多线程同时访问,所有实例
方法、方法某区域前均可
类型:四种
实例方法:同步在拥有该方法的对象上,
静态方法同步:同步在该方法所在的类对象上,同时只允许一个线程执行同一个类的静态同步方法
实例方法:this为调用add的实例本身,一次只有一个线程在同步于同一个监视器对象的Java方法内执行
public void add(int value){
synchronized(this){
this.count += value;
}
}
在同步构造器中用括号括起来的对象叫做监视器对象
同步实例方法使用调用方法本身的实例作为监视器对象
thread、runnable
继承thread不适合资源共享
实现runnable接口
资源共享
多个相同程序代码去处理同一个资源
避免java中单继承限制
健壮性、可被多线程共享、代码和数据独立
线程池只能放入实现runnable、callable类的线程
BufferReader思想:http://www.cnblogs.com/skywang12345/p/io_23.html
为其它Reader提供缓冲功能。
创建BufferReader时,通过构造函数指定某个Reader为参数。
BufferReader将该Reader中的数据分批读取,每次读取一部分到缓冲中;
操作完缓冲中的这部分数据之后,再从Reader中读取下一部分的数据
lock:解决同步、处理资源争夺
ReentrantLock
可重入,可以继续持有锁,释放对等次数真正释放
new .lock .unlock
ReentrantReadWriteLock.ReadLock
ReentrantReadWriteLock.WriteLock
lock阻塞、trylock无阻塞、lockInterruptily可打断
与synchronized:
自由定义多把锁的加解锁顺序,s先加后解
容器类:
BlockingQueue阻塞队列:单向 头添尾删、取FIFO
ArrayListBlockingQueue
LinkedListBlockingQueue
DelayQueue
SynchronousQueue
ConcurrentHashMap:高效的线程安全哈希map
管理类:管理线程、提供机制利用上述工具
ThreadPoolExecutor:五种线程池
参数详解: http://ifeve.com/java-threadpool/
corePoolSize:池内线程初始值与最小值,就算是空闲状态,也会保持该数量线程。
maximumPoolSize:线程最大值,线程的增长始终不会超过该值。
keepAliveTime:当池内线程数高于corePoolSize时,经过多少时间多余的空闲线程才会被回收。回收前处于wait状态
unit:时间单位,可以使用TimeUnit的实例,如TimeUnit.MILLISECONDS
workQueue:待入任务(Runnable)的等待场所,该参数主要影响调度策略,如公平与否,是否产生饿死(starving)
threadFactory:线程工厂类,有默认实现,如果有自定义的需要则需要自己实现ThreadFactory接口并作为参数传入。
https://www.cnblogs.com/wxd0108/p/5479442.html
http://ifeve.com/java-threadpool/
线程池过程分析、关闭过程、配置线程池、
CPU密集型任务配置尽可能少的线程数量,如配置Ncpu+1个线程的线程池。
IO密集型任务则由于需要等待IO操作,线程并不是一直在执行任务,则配置尽可能多的线程,如2*Ncpu。
混合型的任务
如可拆分,拆成一个CPU密集型任务和一个IO密集型任务,只要这两个任务执行的时间相差不是太大,那么分解后执行的吞吐率要高于串行执行的吞吐率
如果这两个任务执行时间相差太大,则没必要进行分解。我们可以通过Runtime.getRuntime().availableProcessors()方法获得当前设备的CPU个数。
建议使用有界队列,有界队列能增加系统的稳定性和预警能力
监控:
通过池提供的参数
taskCount:线程池需要执行的任务数量。
completedTaskCount:线程池在运行过程中已完成的任务数量。小于或等于taskCount。
largestPoolSize:线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过。如等于线程池的最大大小,则表示线程池曾经满了。
getPoolSize:线程池的线程数量。如果线程池不销毁的话,池里的线程不会自动销毁,所以这个大小只增不减。
getActiveCount:获取活动的线程数。
通过扩展线程池:监控时间
通过继承线程池并重写线程池的beforeExecute,afterExecute和terminated方法,我们可以在任务执行前,执行后和线程池关闭前干一些事情
http://www.cnblogs.com/skywang12345/p/io_23.html