Java多线程随笔
最近匆匆的看了一下多线程的知识,其实在我们现在的系统中,我只在一个地方用了多线程,异步刷缓存的时候使用到了。其它地方并没有使用。这个可能跟公司局限性业务有关系,毕竟大家都听过一句话,20%的人掌握着80%的财富。而我们服务的就是那20%里面的一部分。
多线程的产生
硬件的摩尔定律已经被打破了,所以现在多核处理器下使用多线程那是大大的提高效率啊。毕竟5个人同时赚钱,跟5个人轮流赚钱那可不是差的一点半点。所以为了合理的利用资源,那必须的挤榨一点机器性能啊。
上下文切换
多线程未必一定比单线程快,为什么?每个东西都是有正反面的。多线程其实对于计算机来说是一种cpu时间切片。像《java并发编程艺术》里面说的,你在看英文书的时候,如果在某一页遇到不知道的单词,你停下来查字典,查完字典你还得返回去继续读。这个过程中读书,查字典就是两个线程,你就是cpu,你给每个线程一些时间让他们做自己的事情。但是在这个过程中,在你从看书切换到查字典再切换到看书这个过程中,你其实还需要记住看书的位置吧,这种从一件事切换到另一件事再从另一件事切回来,总的有耗费吧?术语称之为上下文切换。
减少上下问切换的方式:
- 无锁并发编程。使用hash算法进行数据id取模分段,特定的线程处理不同段的数据
- 使用cas算法,java的atomic包,cas=compare and swap
- 使用最少线程,避免创建不必要的线程
- 使用协程,在单线程里面实现多任务调度,并在单线程里面维持多个任务间的切换。
死锁
死锁的概念就是有两个线程A,B。线程A,B都需要a,b资源,线程A已经占有了a资源,需要b资源,线程B已经占有了b资源,需要a资源;所以A等待B,B等待A。这样就造成了死锁。这个就是那个著名的哲学家吃饭的问题,5个人,5根筷子,嗯就是这个问题。
线程执行任务
runnable接口,不带返回值
Callable接口,返回Future对象
定义任务:实现runnable,重写run方法。一个线程都需要使用Thread.start()进行启动。线程的运行由线程调度器来选择,线程调度机制非确定性的。
callable接口—->实现call()—->executorService.submit()—->Future<—–访问Future的isDone()是否完成
线程池
FixedThreadPool
:一次性预先加载线程,限制线程的数量;CachedThreadPool
:创建与所需数量相同的线程;SingleThreadPool
:线程数量为1的fixedThreadPool;
sleep()和wait()的区别
sleep()调用的时候不会释放锁,wait()是会阻塞当前线程同时释放锁。
线程优先级
优先级别主要是给线程调度器用,如果同一优先级也是随机的。建议使用MAX_PRIORITY
,NORM_PRIORITY
,MIN_PRIORITY
。
线程让步:yield(),然后相同优先级的其它线程;
join(),自己会挂起,让join的线程先完成;
后台线程,在调用start方法之前设置daemon。
java并发包
java有个juc的并发包。要再仔细看看。