信号量
信号量,有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源,一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个资源申请请求,然后再获取该许可。信号量提供一个方法添加一个许可,从而可能释放一个正在阻塞的获取者。
线程池
线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使应用程序响应更快。
Runnable与Callable两个接口的区别在于:
Runnable提供的任务方法为run,它不能返回任何的结果。Callable接口提供的任务方法为call,它可以返回任务执行后的结果。
public class Pool {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService excutorService=Executors.newSingleThreadScheduledExecutor();
Future<?>task=excutorService.submit(()->{//?不知道具体类型
System.out.println("Callable异步任务");
return "Callable的返回值";//有返回值
});
System.out.println("task.get()="+task.get());
Pool1();//运行Runnable
}
private static void Pool1() {
ExecutorService excutor=Executors.newSingleThreadExecutor();
Future future=excutor.submit(()->{
System.out.println("Runnable异步运行");
});//无返回值
try {
System.out.println("future.get()="+future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
Lock接口及重入锁
Lock的默认实现:ReentrantLock:可重入的独占锁,该对象与synchronized关键字有着相同的表现和更清晰的语义,而且还具有一些扩展的功能。可重入锁被最近的一个成功lock的线程占有(unlock后释放)。该类有一个重要特性体现在构造器上,构造器接受一个可选参数,是否是公平锁,默认是非公平锁。
公平锁:先来一定先排队,一定先获取锁。
非公平锁:不保证上述条件,非公平锁的吞吐量更高。
ThreadLocal
可以再同一个线程中共享变量。
ThreadLocal用来解决多线程程序的并发问题,ThreadLocal并不是一个Thread,而是Thread的局部变量,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
原子操作类
原子操作类相当于泛化的volatile变量,能够支持原子读取-修改-写操作。比如AtomicInteger表示一个int类型的数值,提供了get和set方法,这些volatile类型的变量在读取与写入上有着相同的内存语义。原子操作类在Java.util.concurrent.atomic包下,可以分为四种类型的原子更新类:
原子更新基本类型
原子更新数组类型
原子更新引用
原子更新属性
使用原子方式更新基本类型:
AtomicBoolean:原子更新布尔变量
AtomicInteger:原子更新整型变量
AtomicLong:原子更新长整型变量
具体到每个类,提供的方法基本相同
生产者-消费者模式
生产者-消费者模式描述一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。