CountDownLatch : 监听某些初始化操作 初始化完成后 通知主线程继续工作,比如zookeeper,在开始的时候开始web要先连接一下,初始化一些实例,因此要等连接真正成功了才能初始化,所以可以用countDownLatch来监控。
final CountDownLatch countDown = new CountDownLatch(2);
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("进入线程t1" + "等待其他线程处理完成...");
countDown.await();
// 等待阻塞在这里了,因为 new CountDownLatch(2)所有如果有两个线程发出countDown的时候 此线程继续
System.out.println("t1线程继续执行...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("t2线程进行初始化操作...");
Thread.sleep(3000); // 睡眠
System.out.println("t2线程初始化完毕,通知t1线程继续...");
countDown.countDown(); // 发出一个countDown信号
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("t3线程进行初始化操作...");
Thread.sleep(4000);
System.out.println("t3线程初始化完毕,通知t1线程继续...");
countDown.countDown(); // 发出一个countDown信号
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t3.start();
CyclicBarrier: 每一个线程都要准备好才出发,只要有一个没准备好久都等待。多用于多台机器同一时间要执行任务时使用
static class Runner implements Runnable {
private CyclicBarrier barrier;
private String name;
public Runner(CyclicBarrier barrier, String name) {
this.barrier = barrier;
this.name = name;
}
@Override
public void run() {
try {
Thread.sleep(1000 * (new Random()).nextInt(5));
System.out.println(name + " 准备OK.");
barrier.await(); // 等待,new CyclicBarrier(3) 三个运动员都准备好才放行,调用await三次
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(name + " Go!!");
}
}
public static void main(String[] args) throws IOException, InterruptedException {
CyclicBarrier barrier = new CyclicBarrier(3); // 3
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(new Thread(new Runner(barrier, "zhangsan")));
executor.submit(new Thread(new Runner(barrier, "lisi")));
executor.submit(new Thread(new Runner(barrier, "wangwu")));
executor.shutdown();
}
CountDownlatch 是一个线程等待其他N各线程等待给我发通知 然后一个线程运行
CyclicBarrier 是多个等待互相等待 多个运行。
Callable/Future: 适用于耗时时间长。
private String para;
public UseFuture(String para){
this.para = para;
}
/**
* 这里是真实的业务逻辑,其执行可能很慢
*/
@Override
public String call() throws Exception {
//模拟执行耗时
Thread.sleep(5000);
String result = this.para + "处理完成";
return result;
}
//主控制函数
public static void main(String[] args) throws Exception {
String queryStr = "query";
//构造FutureTask,并且传入需要真正进行业务逻辑处理的类,该类一定是实现了Callable接口的类
FutureTask<String> future = new FutureTask<String>(new UseFuture(queryStr));
FutureTask<String> future2 = new FutureTask<String>(new UseFuture(queryStr));
//创建一个固定线程的线程池且线程数为1,
ExecutorService executor = Executors.newFixedThreadPool(2);
//这里提交任务future,则开启线程执行RealData的call()方法执行
//submit和execute的区别: 第一点是submit可以传入实现Callable接口的实例对象, 第二点是submit方法有返回值
Future f1 = executor.submit(future); //单独启动一个线程去执行的,线程池开的一个,非主线程
Future f2 = executor.submit(future2);
System.out.println("请求完毕");
try {
//这里可以做额外的数据操作,也就是主程序执行其他业务逻辑
System.out.println("处理实际的业务逻辑...");
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
//调用获取数据方法,如果call()方法没有执行完成,则依然会进行等待,FutureTask是异步的。aaa先打印 future的数据后打印
System.out.println("数据:" + future.get());
System.out.println("数据:" + future2.get());
System.out.println("aaa");
executor.shutdown();
}
Semaphore : 信号量适合高并发,许可进入票,限流 不过一般不推荐这样 ,因为这样效率低。
PV(page view) 网站总访问量,刷一次记一次 ,
UV (unique visitor):一个IP只记录一次
QPS(query per second): 每秒查询数,一次查询可能有好多query,可能根据这个参数看一下是否繁忙。会记录日志, 之后调优数据库 服务器等。
RT (response time): 请求相应时间。
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5个线程同时访问
final Semaphore semp = new Semaphore(5);
// 模拟20个客户端访问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可,只有5个线程可以进来,有一个空位 别的才能进来 ,做到限流。
semp.acquire();
System.out.println("Accessing: " + NO);
//模拟实际业务逻辑
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semp.release();
} catch (InterruptedException e) {
}
}
};
exec.execute(run);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println(semp.getQueueLength());
// 退出线程池
exec.shutdown();
}