早起占坑
多线程问题,先要搞清楚两个概念:
并发(concurrent):并发指宏观上同时进行,微观上同一时刻只有一个任务在执行。一般指单核多线程下为并发。
并行(parallel):并行指宏观上同时进行,微观上同一时刻确实是多个任务同时执行。多核处理器可以并行执行多个任务。
为什么需要多线程呢?
可以拿分时多用户操作系统来理解,我们的电脑为什么可以同时听歌、放电影、看网页,,,并不是因为电脑中有多个处理器在分别干这个事情,
而是操作系统将处理器分成一个个小的时间片,这些任务轮换着使用时间片,因为时间片的切换速度非常快,可能一秒内可以切换几百万次时间片,
而CPU的处理速度也同样非常快,可能程序中的一个小的交互任务只需要一两个、十个八个时间片,对用户来说,这么快速的处理和切换是感受不到的,
所以,实现了一个CPU同时处理多个任务,而不是排队处理任务。
试想我们顺序执行听歌、放电影、看网页,对用户的排队等待时间是个极大的浪费,对CPU等待用户交互的时间也是极大的浪费,应该在这个任务等待的时间去处理其它任务。
在一个程序进程中的线程也是同样的道理,如果进程内的一个交互任务可以切换成许多个小的任务,比如多文件的读写,或边读文件边相应用户其它操作,
同样可以通过时间片的轮转同时进行不同的任务或相同任务的拆分,多线程提高了CPU的利用率,节省了用户的等待时间,提高CPU的利用率,提高了整体工作效率。
以后理解多线程,就可以拿听歌、看电影、看网页来理解。
正是CPU的运力极高,由于听歌、看电影并不会占用百分百的CPU时间,所以可以利用CPU闲时并发处理更多的任务,
如果是多个纯CPU运算任务,并发并不会减少计算的总时间,甚至会略有延长,但是多任务共同推进,对用户更加友好。
当然日常应用中绝大多数的任务都存在io等非CPU操作,所以,在这些任务中使用并发可以提高程序运行效率。
使用并发提对我们来说提高了啥?优点
1.减少响应时间,提升用户体验。可以对每个任务同时推进,即时响应,减少用户等待时间。参考看电影同时放音乐。
2.提高CPU利用率,提高运行效率。分多线程来执行耗时操作,记录日志,访问数据库等,同样写入五十万条数据,效率更高。
啥时候用多线程?
参考上面的多线程的优点,第一条对任何时候都适用。
第二条适用于有交互或io、数据库操作、网络请求的情况。
什么是线程安全?
因为多线程下,多个任务同时推进,首先他们共享进程内的资源,其次,他们执行的任务可能会共享某些变量,数据,
如果在读取和写入中间,穿插了其它的线程的一顿操作,很可能使数据出现错误的情况,
比如常说的,并发地买火车票的情况,线程1读取剩余票数后,中间有其它线程改变了剩余票数,然后线程1再进行接下来的操作,就会出问题,
如何解决线程安全问题?
Java提供了两种方式:
1.synchronized
将代码段的变量锁定,(可以加在代码段或方法中,应该尽可能缩小锁的范围)。一个线程进入后,将锁定标记,其它线程阻塞排队,然后解锁后,顺序执行。
为什么应该尽量缩小锁定范围呢,因为如果你在执行非互斥资源的处理,你对互斥资源的锁定,会影响其它需要互斥资源的线程继续执行,从而影响效率。
2.lock
lock提供了可以自定义设置的锁。
lock的锁定和解锁需要手动调用,所以使用lock时,一般将unlock写到finally中,防止出现异常不能释放锁。
lock还提供了trylock,使用trylock如果检查互斥资源被锁定,可以选择立即返回还是继续排队等待,并且trylock还可以设置排队等待时间。,
所以lock比synchronization控制更加自由
另外,Java提供一些实现了线程安全的类,比如集合中的concurrent集合,可以看一下,,,,并且可以看一下jdk实现线程安全时,有没有什么更加高明的处理方式。
留下两个小任务,回头有时间做一下,
1.实现一个线程安全的模拟抢票
2.看一下jdk中的线程安全集合是如何处理线程安全的,有没有其它线程安全类和线程安全处理方式