Concurrent.util常用类

1、CyclicBarrier

假设有只有的一个场景:每个线程代表-一个 跑步运动员,当运动员都准备好后,才一起出发,只要有个人没有准备好,大家都等待。

测试:

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierTest implements Runnable {
	
	private CyclicBarrier cyclicBarrier;
	private String name;
	
	public CyclicBarrierTest(CyclicBarrier cyclicBarrier, String name) {
		this.cyclicBarrier = cyclicBarrier;
		this.name = name;
	}
	
	@Override
	public void run() {
		try {
			Thread.sleep(new Random().nextInt(5000));
			System.out.println(name + "准备完成");
			cyclicBarrier.await();
			System.out.println(name + "开始执行!");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}
		
	}
	
	public static void main(String[] args) {
		CyclicBarrier barrier = new CyclicBarrier(3);
		Thread t1 = new Thread(new CyclicBarrierTest(barrier, "张三"));
		Thread t2 = new Thread(new CyclicBarrierTest(barrier, "李四"));
		Thread t3 = new Thread(new CyclicBarrierTest(barrier, "王五"));
		
		t1.start();
		t2.start();
		t3.start();
	}
	
}

结果:

2、CountDownLacth

他经常用于监听某些初始化操作,等初始化执行完毕后,通知主线程继续工作

注意: CyclicBarrier和CountDownL .acth的区别

测试:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchTest {

	public static void main(String[] args) {
		final CountDownLatch countDown = new CountDownLatch(2);
		
		Thread t1 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("线程t1执行完成");
				countDown.countDown();
			}
		}, "t1");
		
		Thread t2 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("线程t2执行完成");
				countDown.countDown();
			}
		}, "t2");
		
		t1.start();
		t2.start();
		
		try {
			countDown.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("main线程执行完毕");
		
		
	}
	
}

结果:

3、Callable和Future使用

jdk封装的Future的使用。

Future模式非常适合在处理很耗时很长的业务逻辑时进行使用,可以有效的减小系统的响应时间,提高系统的吞吐量。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class FutureTest implements Callable<String>{

	@Override
	public String call() throws Exception {

		Thread.sleep(4000);//假设处理数据需要4s
		
		return "Result";
	}
	
	public static void main(String[] args) throws Exception {
		FutureTask<String> future = new FutureTask<String>(new FutureTest());
		ExecutorService pool = Executors.newFixedThreadPool(1);
		Future judeg = pool.submit(future);
		if(judeg.get() == null) {
			System.out.println("执行结束。。。。。");
		}
		
		System.out.println(future.get());
		
		pool.shutdown();
	}

}

结果:

4、信号量

在Semaphore信号量非常适合高并发访问,新系统在上线之前,要对系统的访问量进行评估,当然这个值肯定不是随便拍拍脑袋就能想出来的,是经过以往的经验、数据、历年的访问量,已经推广力度进行一个合理的评估,当然评估标准不能太大也不能太小,太大的话投入的资源达不到实际效果,纯粹浪费资源,太小的话,某个时间点一个高峰值的访问量上来直接可以压垮系统。

相关概念:

PV (page view)网站的总访问量,页面浏览量或点击量,用户每刷新- -次就会被记录一次。

UV_ (unique Visitor)访问网站的- -台电脑客户端为个访客。- -般来讲,时间上以00:00.24:00之内相同ip的客户端只记录次。

QPS (query per second)即每秒查询数, qps很大程度上代表了系统业务上的繁忙程度,每次请求的背后,可能对应着多次磁盘/O,多次网络请求,多个cpu时间片等。我们通过qps可以非常直观的了解当前系统业务情况,- -旦当前gps超过所设定的预警阀值,可以考电增加机器对集群扩容,以免压力过大导致宕机,可以根据前期的压力测试得到估值,在结合后期综合运维情况,估算出阀值。

RT (response time)即请求的响应时间,这个指标非常关键,直接说明前端用户的体验,因此任何系统设计师都想降低r时间。

当然还涉及cpu、内存、网络、磁盘等情况,更细节的问题很多,如select、 update、delete/ps等数据库层面的统计。

 

Semaphore使用:信号量为几,同时执行的线程数就是几。

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreTest {

	public static void main(String[] args) {
		
		ExecutorService pool = Executors.newCachedThreadPool();
		
		final Semaphore semp = new Semaphore(5);
		
		for(int i = 0; i < 20; i++) {
			
			final int no = i;
			Thread t = new Thread(new Runnable() {
				
				@Override
				public void run() {
					try {
						semp.acquire();//获得许可
						System.out.println("执行线程" + no);
						TimeUnit.SECONDS.sleep(new Random().nextInt(10));
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					semp.release();//释放许可
				}
			});
			
			pool.execute(t);
			
		}
		
		pool.shutdown();
	
	}
	
}

5、容量评估

容量评估:一般来说通过开发、运维、测试、以及业务等相关人员,综合出系统的一系列阀值,然后我们根据关键阀值如qps、rt等,对系统进行有效的变更。

一般来讲, 我们进行多轮压力测试以后,可以对系统进行峰值评估,采用所谓的80/20原则,即80%的访问请求将在20%的时间内达到。这样我们可以根据系统对应的PV计算出峰值qps.

峰值qps= (总PV X 80%)1 (60X 60 X 24 X 20%)

然后在将总的峰值qps除以单台机器所能承受的最高的qps值,就是所需要机器的数量:机器数=总的峰值qps I压测得出的单机极限qps

当然不排除系统在上线前进行大型促销活动,或者双十一-、双十二热点事件、遭受到DDos攻击等情况,系统的开发和运维人员急需要了解当前系统运行的状态和负载情况,-般都会有后台系统去维护。

Semaphore可以控制系统的流量:

拿到信号量的线程可以进入,否则就等待。通过acquire()和release()获取和释 放访问许可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值