Java-线程池 原子性 类

文章详细介绍了Java中的线程池创建,包括Executors的静态方法和直接创建ThreadPoolExecutor,以及线程池的核心参数和操作方法。此外,文章还讨论了原子性变量如AtomicInteger的使用,volatile关键字的问题与解决方案,并对比了悲观锁和乐观锁的区别。最后,提到了并发工具类如Hashtable、ConcurrentHashMap以及CountDownLatch和Semaphore的作用和使用方法。
摘要由CSDN通过智能技术生成

线程池

构造方法

调用Executors静态方法创建

创建一个默认无限大小的线程池(最大不超过int的范围):

static ExecutorService newCachedThreadPool():ExecutorService es = Executors.newCachedThreadPool();
	
	
创建一个指定大小最多线程数量的线程池:

static newFixedThreadPool(int nThreads):ExecutorService es = Executors.newCachedThreadPool();

调用方法

Future<?> submit(Runnable task)  // 提交一个 Runnable 任务用于执行,()里可以传一个λ表达式,也可以传实现Runnable对象
 
void shutdown  关闭线程池

使用Executors中所提供的静态方法来创建

直接创建线程池对象

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(核心线程数量,最大线程数量,空闲线程最大存活时间,任务队列,创建线程工厂,任务的拒绝策略);

参数一:核心线程数量   -------------->   核心线程数量   (不能小于0)

参数二:最大线程数   -------------->   线程池中最大线程的数量   (不能小于等于0,最大数量 >= 核心线程数量)

参数三:空闲线程最大存活时间   -------------->   空闲时间(值)   (不能小于0)

参数四:时间单位   -------------->   空闲时间(单位)   (时间单位)
                           (秒:TimeUnit.SECONDS 分:TimeUnit.MINUTES 时:TimeUnit.HOURS ...)

参数五:任务队列   -------------->   阻塞队列   (不能为null)
							(new ArrayBlockingQueue<>(int capacity)) //任务队列

参数六:创建线程工厂   -------------->   创建线程的方式   (不能为null)
								(Executors.defaultThreadFactory())
  
参数七:任务的拒绝策略   -------------->   要执行的任务过多时的解决方案   (不能为null)
								(new ThreadPoolExecutor.AbortPolicy())
任务的拒绝策略

ThreadPoolExecutor.AbortPolicy:  丢弃任务并抛出RejectedExecutionException异常。--是默认的策略。

ThreadPoolExecutor.DiscardPolicy:  丢弃任务,但是不抛出异常 这是不推荐的做法。

ThreadPoolExecutor.DiscardOldestPolicy: 抛弃队列中等待最久的任务 然后把当前任务加入队列中。

ThreadPoolExecutor.CallerRunsPolicy:     调用任务的run()方法绕过线程池直接执行。

原子性

volatile-问题

出现原因:

当A线程修改了共享数据时,B线程没有及时获取到最新的值,如果还在使用原先的值,就会出现问题 
	1 ,堆内存是唯一的,每一个线程都有自己的线程栈。

	2 ,每一个线程在使用堆里面变量的时候,都会先拷贝一份到变量的副本中。

	3 ,在线程中,每一次使用是从变量的副本中获取的。

volatile解决

Volatile关键字 :强制线程每次在使用的时候,都会看一下共享区域最新的值
	例: public static volatile int money = 1000;    //每个线程使用前都会重新获取此值

原子性

所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,是一个不可分割的整体

AtomicInteger的常用方法

public AtomicInteger()        //初始化一个默认值为0的原子型Integer
public AtomicInteger(int initialValue)     //初始化一个指定值的原子型Integer
    
AtomicBoolean: 原子更新布尔类型   //与AtomicInteger相似

AtomicLong:	原子更新长整型     //与AtomicInteger相似
    

int get():   	//获取值

int getAndIncrement():     //以原子方式将当前值加1,注意,这里返回的是自增前的值。

int incrementAndGet():   //以原子方式将当前值加1,注意,这里返回的是自增后的值。

int addAndGet(int data):	//以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果。

int getAndSet(int value):   //以原子方式设置为newValue的值,并返回旧值。

悲观锁和乐观锁

synchronized(悲)和CAS(乐)的区别

相同点:在多线程情况下,都可以保证共享数据的安全性。

不同点:synchronized总是从最坏的角度出发,认为每次获取数据的时候,别人都有可能修改。所以在每次操作共享数据之前,都会上锁。(悲观锁)

cas是从乐观的角度出发,假设每次获取数据别人都不会修改,所以不会上锁。只不过在修改共享数据的时候,会检查一下,别人有没有修改过这个数据。
如果别人修改过,那么我再次获取现在最新的值。            
如果别人没有修改过,那么我现在直接修改共享数据的值.(乐观锁)

乐观锁:
	1: 只针对 值的修改  只在修改处 加校验。  具体大段的逻辑 他不管。
	2: 针对 多查  少改。 
悲观锁(synchronized)
	1: 针对 大段的逻辑 上下文关联的

并发工具类

Hashtable集合

HashMap 线程不安全的 效率比较高。 开发中在局部位置定义双列集合,首选HashMap,因为局部位置不涉及共享数据 ,属于单线程开发,使用HashMap效率最高。

Hashtable  每个方法都是 同步方法,用synchronized修饰 。   效率比较低

ConcurrentHashMap

线程安全 效率较高
原理:
jdk1.7之前原理:
	使用的 哈希表的嵌套, 并使用悲观锁synchronized对 小哈希表进行局部锁定,所以他可以同时使用16条线程共同操作此集合。
jdk1.8之后的原理:
	对横向的数组数据 使用乐观锁cas
	对竖向的链表和红黑树 使用悲观锁synchronized 锁对象是红黑树或者链表的头结点。

CountDownLatch

可以设置 某一线程 等待其他几条线程结束之后 再开始执行
方法
构造方法:
public CountDownLatch(int count)   参数传递线程数,表示等待线程数量
    
成员方法:
public void await()     让线程等待
public void countDown()      当前线程执行完毕

Semaphore

限制同一时间线程执行的个数,可以控制访问特定资源的线程数量。
方法:
构造方法:
public Semaphore(int count)  // 参数传递可执行的线程数量

方法:
public void acquire()    //从此信号量获取一个许可,在提供一个许可前一直将线程阻塞
public void release()    //释放一个许可,将其返回给信号量。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江東-H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值