java并发工具类-Semaphore
java并发工具类-Semaphore
Semaphore简介 Semaphore也叫信号量,在JDK1.5被引入,可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。
Semaphore内部维护了一组虚拟的许可,许可的数量可以通过构造函数的参数指定。
访问特定资源前,必须使用acquire方法获得许可,如果许可数量为0,该线程则一直阻塞,直到有可用许可。
访问资源后,使用release释放许可。
Semaphore和ReentrantLock类似,获取许可有公平策略和非公平许可策略,默认情况下使用非公平策略。
通俗的讲Semaphore是一种在多线程环境下使用的设施,该设施负责协调各个线程,以保证它们能够正确、合理的使用公共资源的设施,也是操作系统中用于控制进程同步互斥的量。Semaphore是一种计数信号量,用于管理一组资源,内部是基于AQS的共享模式。它相当于给线程规定一个量从而控制允许活动的线程数。
是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源
应用场景 Semaphore 是 synchronized 的加 ...
CompletableFuture
前言 CompletableFuture类实现了CompletionStage和Future接口。Future是Java 5添加的类,用来描述一个异步计算的结果,但是获取一个结果时方法较少,要么通过轮询isDone,确认完成后,调用get()获取值,要么调用get()设置一个超时时间。但是这个get()方法会阻塞住调用线程,这种阻塞的方式显然和我们的异步编程的初衷相违背。
为了解决这个问题,JDK吸收了guava的设计思想,加入了Future的诸多扩展功能形成了CompletableFuture。
敲黑板:以Async结尾的方法都是可以异步执行的,如果指定了线程池,会在指定的线程池中执行,如果没有指定,默认会在ForkJoinPool.commonPool()中执行
Future
Future是Java 5添加的类,用来描述一个异步计算的结果。你可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算完成返回结果,你也可以使用cancel方法停止任务的执行。
public class BasicFuture {
public static void ...
java并发工具类-Exchanger
java并发工具类-Exchanger
Exchanger 简介 Exchange位于JUC包下面,主要是用于线程之间数据交换的工具类,经常用于管道设计和遗传算法中,Exchanger用于进行线程间的数据交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。这两个线程通过exchange 方法交换数据,如果第一个线程先执行exchange 方法,它会一直等待第二个线程也执行exchange 方法,当两个线程都到达同步点时,这两个线程就可以交换数据。
可以将Exchange看做是一个双向数据传输的SynchronousQueue。
此类提供对外的操作是同步的;
用于成对出现的线程之间交换数据;
可以视作双向的同步队列;
可应用于基因算法、流水线设计等场景。
Exchanger 提供的方法构造方法/**
* Creates a new Exchanger.
*/
public Exchanger() {
participant = new Participant();
}
创建一个新的Exchange。
主要方法这个类提供对外的接口非常简洁, ...
java并发工具类-线程池
java并发工具类-线程池
什么是线程池之前我们在使用多线程都是用Thread的start()来创建启动一个线程,但是在实际开发中,如果每个请求到达就创建一个新线程,开销是相当大的。服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。这就引入了线程池概念。
线程池的原理其实就是对多线程的一个管理,为了实现异步机制的一种方法,其实就是多个线程执行多个任务,最终这些线程通过线程池进行管理不用手动去维护一次可以处理多个任务,这样就可以迅速的进行相应比如说一个网站成为了热点网站,那么对于大量的点击量,就必须要对每一次的点击做出迅速的处理,这样才能达到更好的交互效果,这样就需要多个线程去处理这些请求,以便能够更好的提供服务。
为什么使用线程池 操作系统创建线程、切换线程状态、终结线程都要进行CPU调度——这是一个耗费时间和系统资源的事情。
大多数实际场景中是这样的:处理某一次请求 ...
java并发工具类-队列
java并发工具类-队列
BlockingQueue
java.util.concurrent包中的Java BlockingQueue接口表示一个线程可以安全放入以及从中获取实例的队列。在本文中,我将向你展示如何使用BlockingQueue。
使用
一个BlockingQueue通常用于在线程上生成对象,另一个线程消耗对象。这是一个说明这个原则的图表:
生产线程将一直生成新对象并将它们插入队列,直到达到队列的容量上限。如果阻塞队列达到其上限,则在尝试插入新对象时会阻止生产线程。它将一直被阻塞,直到消费线程将一个对象从队列中取出。
消费线程不断将对象从阻塞队列中取出并处理它们。如果消费线程试图将对象从空队列中取出实例,那么消费线程将被阻塞,直到生产线程向队列放入一个对象。
方法
BlockingQueue有4组不同的方法用于插入,删除和检查队列中的元素。当不能立即执行所请求的操作时,每组方法的行为会不同。这是一个方法表:
抛出异常
返回特殊值
阻塞
超时
插入
add(o)
offer(o)
put(o)
offer(o, timeout, timeun ...
JAVA中的线程安全
JAVA中的线程安全
什么是线程安全
当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在调用代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。
指多个线程在执行同一段代码的时候采用加锁机制,使每次的执行结果和单线程执行的结果都是一样的,不存在执行程序时出现意外结果。
线程不安全:是指不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。
线程封闭
实现好的并发是一件困难的事情,所以很多时候我们都想躲避并发。避免并发最简单的方法就是线程封闭。什么是线程封闭呢?就是把对象封装到一个线程里,只有这一个线程能看到此对象。那么这个对象就算不是线程安全的也不会出现任何安全问题。实现线程封闭有哪些方法呢?
ad-hoc线程封闭:
这是完全靠实现者控制的线程封闭,他的线程封闭完全靠实现者实现。Ad-hoc线程封闭非常脆弱,应该尽量避免使用。
栈封闭:
栈封闭是我们编程当中遇到的最多的线程封闭。什么是栈封闭呢?简单的说就是局部变量。多个线程访问一个方法,此方法中的局部变量都会被拷贝一份到线程栈 ...
JAVA线程池实现03-其余方法
JAVA线程池实现03-其余方法
shutdown安全停止任务
注意该方法不会马上停止线程池,会先将线程池置于shutdown状态然后发起中断请求,等待任务自己结束,线程内部要实现中断请求的响应处理,否则就不会终止。
//安全的中断任务
public void shutdown() {
//获取重入锁
final ReentrantLock mainLock = this.mainLock;
//加锁
mainLock.lock();
try {
//检查权限
checkShutdownAccess();
//更改运行状态
advanceRunState(SHUTDOWN);
//中断任务
interruptIdleWorkers();
//模板方法,不继承实现则是一个空方法
onShutdown();
...
JAVA线程池实现02-提交任务
JAVA线程池实现02-提交任务
submit提交任务/**
* 提交一个带有返回值的任务
* @param task 任务
* @param result 结果
* @param <T> 泛型
* @return Future
*/
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
//调用execute进行执行
execute(ftask);
return ftask;
}
/**
* 创建一个FutureTask
* @param runnable 运行的任务
* @param value 返回结果
* @param <T> 泛型
* @return FutureTask
*/
protect ...
JAVA阻塞队列实现
JAVA阻塞队列实现
什么是阻塞队列 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
队列的特点是:先进先出(FIFO)
BlockingQueue的方法
阻塞队列提供了四种处理方法:
方法\处理方式
抛出异常
返回特殊值
一直阻塞
超时退出
插入
add(e)
offer(e)
put(e)
offer(e, time, unit)
移除
remove()
poll()
take()
poll(time, unit)
检查
remove()
peek()
不可用
不可用
抛出异常:是指当阻塞队列满时候,再往队列里插入元素,会抛出IllegalStateException(“Queue full”)异常。当队列为空时,从队列里获取元素时会抛出NoSuchEle ...
java并发工具类-Callable、Future 和FutureTask
java并发工具类-Callable、Future 和FutureTask
前言
创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。
这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。
而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果
Callable接口Callable位于JUC包下,它也是一个接口,在它里面也只声明了一个方法叫做call():
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute ...
JAVA线程池简介
什么是线程池 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。
为什么使用线程池操作系统创建线程、切换线程状态、终结线程都要进行CPU调度——这是一个耗费时间和系统资源的事情。
大多数实际场景中是这样的:处理某一次请求的时间是非常短暂的,但是请求数量是巨大的。这种技术背景下,如果我们为每一个请求都单独创建一个线程,那么物理机的所有资源基本上都被操作系统创建线程、切换线程状态、销毁线程这些操作所占用,用于业务请求处理的资源反而减少了。所以最理想的处理方式是,将处理请求的线程数量控制在一个范围,既保证后续的请求不会等待太长时间,又保证物理机将足够的资源用于请求处理 ...
Pytorch
PyTorch总结PyTorch 简介与安装PyTorch 简介PyTorch 简介2017 年 1 月, FAIR (Facebook AI Research) 发布 PyTorch,它是在 Torch 基础上用 Python 语言重新打造的一款深度学习框架。Torch 是采用 Lua 语言为接口的机器学习框架,但因 Lua 语言较为小众,导致 Torch 知名度不高。
PyTorch 发展
2017 年 1 月正式发布 PyTorch。
2018 年 4 月更新 0.4.0 版,支持 Windows 系统,caffe2 正式并入 PyTorch。
2018 年 11 月更新 1.0 稳定版,已成为 GitHub 上增长第二快的开源项目。
2019 年 5 月更新 1.1.0 版,支持 TensorBoard,增强可视化功能。
2019 年 8 月更新 1.2.0 版,更新 torchvision,torchaudio 和 torchtext,增加更多功能。
2014 年 10 月至 2018 年 2 月 arXiv 论文中深度学习框架提及次数统计:
PyTorch 的增长速度与 ...