.net网站开发程序员,福建省住建厅网站官网,网站建设的前途,项目管理软件工具4 特定场景解决方法
⭐⭐⭐⭐⭐⭐ Github主页#x1f449;https://github.com/A-BigTree 笔记仓库#x1f449;https://github.com/A-BigTree/tree-learning-notes 个人主页#x1f449;https://www.abigtree.top ⭐⭐⭐⭐⭐⭐ 如果可以#xff0c;麻烦各位看官顺手点个st…4 特定场景解决方法
⭐⭐⭐⭐⭐⭐ Github主页https://github.com/A-BigTree 笔记仓库https://github.com/A-BigTree/tree-learning-notes 个人主页https://www.abigtree.top ⭐⭐⭐⭐⭐⭐ 如果可以麻烦各位看官顺手点个star~
如果文章对你有所帮助可以点赞收藏⭐支持一下博主~ 文章目录 4 特定场景解决方法4.1 CountDownLatch实例 4.2 CyclicBarrier实例 4.3 Semaphore4.3.1 常规方式使用4.3.2 引入超时机制4.3.3 应用场景举例 4.4 Fork Join4.4.1 介绍4.4.2 API介绍RescursiveTaskForkJoinTask 4.4.3 案例需求代码 4.1 CountDownLatch
效果指定一个操作步骤数量在各个子线程中每完成一个任务就给步骤数量 - 1在步骤数量减到0之前CountDownLatch 可以帮我们把最后一步操作抑制住阻塞让最后一步操作一直等到步骤被减到 0 的时候执行。
实例
有六名同学在值日班长负责锁门。班长必须确保所有同学都离开教室再锁门。
// 声明一个变量用来保存同学的数量
int stuNum 6;// 创建CountDownLatch对象
CountDownLatch countDownLatch new CountDownLatch(stuNum);// 创建和同学数量相等的线程
for (int i 0; i stuNum; i) {String num String.valueOf(i 1);new Thread(()-{// 完成一次操作System.out.println(Thread.currentThread().getName() num 号同学离开教室);// 让countDownLatch管理的数量-1countDownLatch.countDown();}).start();}// 让countDownLatch负责将最后一步操作抑制住
countDownLatch.await();System.out.println(班长锁门);4.2 CyclicBarrier
支持多线程在执行各自任务的时候到达某个状态点就等待等所有线程都到达这个状态点再继续执行后步骤。
实例
public class DemoO19CyclicBarrierTest {private static ListListString matrix new ArrayList();static {matrix.add(Arrays.asList(normal,special,end));matrix.add(Arrays.asList(normal,normal,special,end));matrix.add(Arrays.asList(normal,normal,normal,special,end));}public static void main(String[] args) {// 1.创建CyclicBarrier对象CyclicBarrier barrier new CyclicBarrier(3);// 2.创建3个线程分别执行各自的任务new Thread(()-{try {ListString list matrix.get(0);for (String value : list) {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName() value value);if (special.equals(value)) {// 遇到特殊任务标记就让当前线程等一下barrier.await();}}} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, thread01).start();new Thread(()-{try {ListString list matrix.get(1);for (String value : list) {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName() value value);if (special.equals(value)) {// 遇到特殊任务标记就让当前线程等一下barrier.await();}}} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, thread02).start();new Thread(()-{try {ListString list matrix.get(2);for (String value : list) {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName() value value);if (special.equals(value)) {// 遇到特殊任务标记就让当前线程等一下barrier.await();}}} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, thread03).start();}}4.3 Semaphore
4.3.1 常规方式使用
使用 Semaphore 可以帮助我们管理资源位当某个线程申请资源时由 Semaphore 检查这个资源是否可用如果其他线程释放了这个资源那么申请资源的线程就可以使用。
// 1、创建 Semaphore 对象指定资源数量为 3
Semaphore semaphore new Semaphore(3);// 2、创建 10 个线程争夺这 3 个资源
for (int i 0; i 10; i) {new Thread(() - {try {// 申请资源semaphore.acquire();// 拿到资源执行操作System.out.println(【 Thread.currentThread().getName() 】号车辆【驶入】车位);TimeUnit.SECONDS.sleep(3);System.out.println(【 Thread.currentThread().getName() 】号车辆【驶出】车位);} catch (InterruptedException e) {e.printStackTrace();} finally {// 操作完成释放资源semaphore.release();}}, i ).start();
}4.3.2 引入超时机制
// 1、设定车位数量
int carPositionCount 3;// 2、创建 Semaphore 对象
Semaphore semaphore new Semaphore(carPositionCount);// 3、创建 50 个线程抢车位
for (int i 0; i 50; i) {int carNum i;new Thread(()-{boolean acquireResult false;try {// 线程开始时先申请资源申请不到会进入等待状态// 申请资源方式一不见不散等不到资源就一直等// semaphore.acquire();// 申请资源方式二过时不候acquireResult semaphore.tryAcquire(3, TimeUnit.SECONDS);if (acquireResult) {// 申请到资源时线程会继续执行System.out.println(carNum 号车辆驶入车位);// 车辆在车位停放一段时间TimeUnit.SECONDS.sleep(2);// 停放完成离开车位System.out.println(carNum 号车辆驶出车位);} else {System.out.println(carNum 号车辆放弃等待);}} catch (Exception e) {e.printStackTrace();} finally {// 判断当前线程释放拿到了资源if (acquireResult) {// 任务执行完成释放资源semaphore.release();}}}).start();} 4.3.3 应用场景举例
借助Semaphore实现『限流』操作。
当前服务器实例能够承受多大的访问量——设置为资源的数量。根据资源的数量创建Semaphore对象。服务器实例接收到请求通过Semaphore对象管理处理请求数量。 在能力范围内处理请求。超过能力范围设定等待时间看是否能够得到别的请求处理完成释放资源。
4.4 Fork Join
4.4.1 介绍
使用 Fork Join 框架能够帮助我们把一个大型任务根据一定规律拆分成小任务执行。如果拆分后的任务还不够小可以以递归模式继续拆分直到拆分到可以执行的程度。然后再把各个子任务执行的结果汇总到一起。
Fork拆分把大任务拆分成小任务。Join合并把小任务执行的结果合并到一起。 4.4.2 API介绍
RescursiveTask 我们使用 Fork Join 框架只需要继承 RecursiveTask然后重写 compute() 方法即可。在 compute() 方法中需要包含
任务拆分的逻辑任务拆分的操作调用 fork() 方法已拆分任务的合并调用 join() 方法子任务结果的合并将 join() 方法的返回值合并起来
ForkJoinTask
ForkJoinTask 类是 RecursiveTask 的父类。 4.4.3 案例
需求
完成从 1~100 的累加。
代码
// 任务类
class MyTask extends RecursiveTask {// 区间开始位置private int begin;// 区间结束位置private int end;// 区间调整值要通过拆分任务将区间调整到 10 以内public static final int ADJUST_VALUE 10;// 保存当前任务的结果private int result 0;// 声明构造器设定当前任务的开始和结束位置public MyTask(int begin, int end) {this.begin begin;this.end end;}Overrideprotected Object compute() {// 1、判断当前区间是否是原子任务中可以执行计算的范围if (end - begin ADJUST_VALUE) {for (int i begin; i end ; i) {result result i;}} else {// 2、计算新拆分任务的区间范围int leftBegin begin;int leftEnd (begin end) / 2;int rightBegin leftEnd 1;int rightEnd end;// 3、创建两个新的任务子任务MyTask myTaskLeft new MyTask(leftBegin, leftEnd);MyTask myTaskRight new MyTask(rightBegin, rightEnd);// 4、调用框架提供的 fork() 进一步拆分任务myTaskLeft.fork();myTaskRight.fork();// 5、调用框架提供的 join() 获取子任务计算的结果int leftResult (int) myTaskLeft.join();int rightResult (int) myTaskRight.join();// 6、把子任务的结果合并到一起result leftResult rightResult;}return result;}}// 测试代码
// 1、创建 Fork Join 任务池
ForkJoinPool pool new ForkJoinPool();// 2、创建任务对象
MyTask myTask new MyTask(1, 100);// 3、将任务对象提交到任务池
ForkJoinTask forkJoinTask pool.submit(myTask);// 4、获取任务执行结果
int finalResult (int) forkJoinTask.get();System.out.println(finalResult finalResult);