线程
1.信号量:
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个 关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。
2.线程池:
概念:线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会 超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。
例:
public class MyExecutor {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService myExecutor = Executors.newScheduledThreadPool(2);
Set<Callable<Integer>> mySet = new HashSet<>();
mySet.add(()->{
String name = Thread.currentThread().getName();
for (int i = 0; i <10; i++) {
System.out.println(name+(i+1)+"只绵羊...");
}
return 1;
});
mySet.add(()->{
String name = Thread.currentThread().getName();
for (int i = 0; i <10; i++) {
System.out.println(name+(i+1)+"粒沙子...");
}
return 1;
});
List<Future<Integer>> result = myExecutor.invokeAll(mySet);
for (Future<Integer> future : result) {
System.out.println("线程任务执行结果"+future.get());
}
myExecutor.shutdown();
}
}
3.Lock接口及重入锁
Lock接口:Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。Lock相对于synchronized关键字而言更加灵活,你可以自由得选择我你想要加锁的地方。当然更高的自由度也带来更多的责任。我们通常会在try...catch模块中使用lock关键字,在finally模块中释放锁
4.重入锁:
定义:重进入是指任意线程在获取到锁之后,再次获取该锁而不会被该锁所阻塞。关联一个线程持有者+计数器,重入意味着锁操作的颗粒度为“线程”。
重入锁实现重入性:每个锁关联一个线程持有者和计数器,当计数器为0时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为0,则释放该锁。
5.ThreadLocal:
ThreadLocal 是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问, 通常是类中的 private static 字段,是对该字段初始值的一个拷贝,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
6.原子操作类:
1.什么是原子操作:
"原子操作(atomic operation)是不需要synchronized",所谓原子操作是指不会被线程调度机制打断的操作;这 种操作一旦开始,就一直运行到结束,中间不会有任何 context switch;java中一般事务管理里面用到原子操作。
原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分,将整个操作视作一个整体是原子性的核心特征。
2.原子操作的好处:
⑴. 性能角度:它执行多次的所消耗的时间远远小于由于线程所挂起到恢复所消耗的时间,因此无锁的CAS操作在性能上要比同步锁高很多;
⑵. 业务需求:业务本身的需求上,无锁机制本身就可以满足我们绝不多数的需求,并且在性能上也可以大大 的进行提升。
7.生产者-消费者模式:
定义:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗。虽然它们任务不同,但处理的资源是相同的,这体现的是一种线程间通信方式。
三种实现方式:
1. 使用Object的wait() / notify()方法
2. 使用Lock和Condition的await() / signal()方法
3. 使用BlockingQueue阻塞队列方法
生产者-消费者模型需注意的点:
1.生产者仅仅在仓储未满时候生产,仓满则停止生产。
2.消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3.当消费者发现仓储没产品可消费时候会通知生产者生产。
4.生产者在生产出可消费产品时候,应该通知等待的消费者去消费。