线程的基础
来源:互联网 发布:网络十大丑男照片 编辑:程序博客网 时间:2024/06/06 02:32
一.进城、线程、协程之间的联系。
进程就可以看做是一个应用程序,而线程是进程的执行单元,多个线程组成一个完整的进程,而协程的话就是线程的拆分,它将线程细分化,能进一步优化并发编程,暂不做细讲。
二.线程的生命周期:
①新生态:Thread t=new Thread();
②就绪:t.start();线程被启动,等待被分配给CPU的时间片,获取CPU资源
③运行:线程获取CPU资源执行run()方法;
④阻塞:由于某些阻塞事件sleep(),wait()....导致线程进入就绪状态,等待重新获取资源
⑤死亡:当线程被杀死或者run()方法运行完。
三.并发编程:
①好处:能最大限度的调度CPU资源,降低等待执行时间,提高系统的吞吐量,提升性能。
②坏处:由串行编程变成并行编程,需要开发人员考虑各种可能由于并行导致的数据不一致、死锁等问题。
四.Volatile和synchronized关键字
①volatile修饰的属性,能保证内存的可见性,但是保证不了原子性。
②synchronized可以锁方法,锁方法快,能保证原子性,用synchronized可以保证程序是串行执行的,它是重量级锁。
关键词:
内存的可见性——》被volatile修饰的属性,值的修改会被其他的线程看见,一旦发现值被修改了,那么其他线程就会将本地工作内存地址废弃,然后重新从CPU的主内存中load属性值。
原子性操作——》形如:a=a+1;a++;这种是非原子操作的,这种在并发编程中是不能保证属性值的正确性的。
五.并发编程常用类:
JDK的集合类:
①List->Collections.synchronizedList()->Vector>CopyOnWriteArrayList;Vector的读性能不如CopyOnWriteArrayList;但是写性能比CopyOnWrite好。
②Set->Collections.synchronizedSet()->CopyOnWriteArrayList
③Map->ConcurrentHashMap[get无锁,put减少锁粒度]
④Queue->LinkedBlockingQueue->ConcurrentLinkedQueue[无锁]
JDK的Util类:java.util.concurrent.atomic
AtomicInteger,AtomicLong,AtomicDouble.......
java.util.concurrent包下
JDK线程池:Executor框架 (对多线程的管理:线程的创建和销毁都是会影响性能的)
ThreadPoolExecutor功能强大的线程池:可以根据工作需要,选择不同的线程池
如:newFixedThreadPool()方法:返回一个固定线程数量的线程池。任务提交到线程池,如果有空余的线程,就立刻执行,如果没有就暂时放到等待队列,等待执行。
newSingleThreadPool()方法,返回只有一个线程的线程池,待线程空闲,按照先进先出的顺序执行。
newCacheThreadPool()方法:返回一个可根据实际情况调整线程数的线程池。优先使用空闲的可复用的线程,如果请求量超过了可用的线程,那么就会创建新的线程执行任务。
newScheduledThreadPool方法:返回一个ScheduledExecutorService对象,可以指定线程数量。主要用于在给定时间或者给定周期定时执行一些功能任务。
可以自定义线程池只要继承ThreadPoolExeutor,也可以对线程池做一些拓展,它自带了beforeExecute和afterExecute方法,可以用于一些信息的记录以及线程池运行状态的跟踪。
六.有锁优化
①在多线程的环境中,我们要尽量避免使用全局变量,应该使用局部变量。全局变量在多线程中是共享的,很容易导致数据不一致问题。
②Synchronized和ReentrantLock重复锁的使用:
Synchronized锁在JDK1.6之前性能是不如Lock的,在JDK1.6之后,synchronized的性能和lock可忽略不计了。Syn相比lock的话可控性要差,Lock支持锁等待时间、锁中断,但是syn代码可读性和维护性好。
使用建议:如果在访问数据库资源不是很慢的情况下,可以选择synchronized,如果数据库操作比较频繁,很容易导致超时的情况下,可以选择Lock。这样就不会导致死锁。
③锁优化
->减少持锁时间,比如用synchronized不是锁整个方法,而是锁方法体内部涉及到资源竞争的部分。
->减少锁粒度,比如ConcurrentHashMap它默认是有16个段,每个段都是一个子hashmap,添加属性、获取属性,都是只会找到对应的其中一段,然后给这一段加锁,而不是将整个hashmap锁住。
->读写锁ReadWriteLock替换独占锁:在读多写少的场合,根据功能的不同,使用读写锁分离能提高并发。
->锁分离:读写锁的延伸。根据应用程序的功能特点,将独占锁,拆分为两把锁。
ReentrantLock take=new ReentrantLock();
Condition notEmpty= take.newCondition();
ReentrantLock put=new ReentrantLock();
Condition full= put.newCondition();
->锁粗化:对于同一个锁,如果总是获取同步和释放,是会影响性能的,所以我们需要减少锁的同步次数。比如for(){synchronized(object){}}和synchronized(Object){for(){}}第一种syn在for循环体内,一直在获取同步和释放。
->JVM的自旋锁:通过执行空循环体。线程上下文的切换是要消耗系统资源的,频繁的挂起和恢复会给系统带来极大的压力,如果线程间的切换所需要的时间比业务处理的时间长,那就不好玩了。而通过自旋这种无锁的方式就能避免切换的耗时。
七.无锁
AtomicInterger整数,AtomicLong长整形,AtomicReference普通对象等。。。。
它们都是通过CAS自旋算法实现无锁原子操作的。
八.无锁并行框架:Amino:Apache下的一个分支项目,提供了用于线程安全的、基于无锁算法的一些数据结构。如:LockFreeList和LockFreeVector。研究表明,它们的性能比JDK提供的加锁的LinkedList和vector性能好。
九.并行程序设计模式:
①:Future模式
②Master-Worker模式
③Guarded Suspension模式
④生产者-消费者模式
十.协程:kilim框架,自行了解。
- 线程的基础
- java 线程的基础
- 线程的基础方法
- 线程的基础概念
- 关于线程(一)线程的基础
- 线程基础—线程的创建
- 线程基础—线程的同步
- 线程的基础学习之创建线程
- 一些基础的线程例子
- Java基础---线程的创建
- Java基础的线程概念
- 【Java基础】:线程的生命周期
- Java基础-线程的通信
- IOS基础--线程的使用
- 线程的建立 (基础)
- java基础---线程的停止
- 线程基础
- 线程基础
- android studio 学习笔记之 注释规范化
- android 封装一些高效方法
- leetcode No75. Sort Colors
- C++ 编译、链接
- 安装了两种版本的jdk后,Eclipse启动失败解决方法
- 线程的基础
- 对数及对比度拉伸变换
- 自定义Toast显示效果
- 【C++】AfxBeginThread
- Leetcode - Array - 66. Plus One(简单模拟)
- 算术表达式的转换
- 【cpp面向对象编程学习笔记】(二)
- android studio 报错分析
- 根据顺序对个数找符合条件的数列