1. JUC - CountDownLatch 倒计时锁
/**
* 倒计时锁
*/
public class CountDownLatchSample {
private static int count = 0;
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(100);
CountDownLatch countDownLatch = new CountDownLatch(10000);
for (int i = 1; i <= 10000; i++) {
final int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
//多个线程运行时 代码需要同步
synchronized (CountDownLatchSample.class){
try {
count = count + index;
} catch (Exception e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}
}
});
}
//倒计时锁await()结束后才继续往后执行
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
//关闭线程池
threadPool.shutdown();
}
}
运行结果
50005000
2. JUC之Semaphore信号量
/**
* Semaphore信号量经常用于限制获取某种资源的线程数量
*/
public class SemaphoreSample {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool();
Semaphore semaphore = new Semaphore(5);//定义5个信号量
for (int i = 1; i <= 20; i++) {
final int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();//获取一个信号量,"占用一个跑道"
play();
semaphore.release();//执行完成后,释放这个信号量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
//关闭线程池
threadPool.shutdown();
}
public static void play() {
try {
System.out.println(new Date() + " " + Thread.currentThread().getName() + ":获得进入服务器资格");
Thread.sleep(2000);
System.out.println(new Date() + " " + Thread.currentThread().getName() + ":退出服务器");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-7:退出服务器
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-10:退出服务器
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-11:获得进入服务器资格
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-14:获得进入服务器资格
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-15:获得进入服务器资格
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-18:获得进入服务器资格
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-19:获得进入服务器资格
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-11:退出服务器
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-14:退出服务器
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-19:退出服务器
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-18:退出服务器
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-15:退出服务器
---------------------------------------------------------------------
/**
信号量已满时 不再执行其它线程
*/
public class SemaphoreSample {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool();
Semaphore semaphore = new Semaphore(5);//定义5个信号量
for (int i = 1; i <= 20; i++) {
final int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
if (semaphore.tryAcquire()) {//尝试获取一次信号量,获取到返回true,否则返回false
play();
semaphore.release();//执行完成后,释放这个信号量
} else {
System.out.println(Thread.currentThread().getName() + ":对不起服务器已满,请稍后再试");
}
}
});
}
//关闭线程池
threadPool.shutdown();
}
public static void play() {
try {
System.out.println(new Date() + " " + Thread.currentThread().getName() + ":获得进入服务器资格");
Thread.sleep(2000);
System.out.println(new Date() + " " + Thread.currentThread().getName() + ":退出服务器");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果
pool-1-thread-5:对不起服务器已满,请稍后再试
pool-1-thread-6:对不起服务器已满,请稍后再试
pool-1-thread-8:对不起服务器已满,请稍后再试
pool-1-thread-9:对不起服务器已满,请稍后再试
pool-1-thread-10:对不起服务器已满,请稍后再试
pool-1-thread-18:对不起服务器已满,请稍后再试
pool-1-thread-19:对不起服务器已满,请稍后再试
pool-1-thread-13:对不起服务器已满,请稍后再试
pool-1-thread-12:对不起服务器已满,请稍后再试
pool-1-thread-17:对不起服务器已满,请稍后再试
pool-1-thread-16:对不起服务器已满,请稍后再试
pool-1-thread-20:对不起服务器已满,请稍后再试
pool-1-thread-14:对不起服务器已满,请稍后再试
pool-1-thread-15:对不起服务器已满,请稍后再试
pool-1-thread-11:对不起服务器已满,请稍后再试
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-3:获得进入服务器资格
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-1:获得进入服务器资格
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-4:获得进入服务器资格
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-7:获得进入服务器资格
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-2:获得进入服务器资格
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-1:退出服务器
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-7:退出服务器
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-4:退出服务器
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-2:退出服务器
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-3:退出服务器
-------------------------------------------------------------------------------------
/**
* 信号量已满时 不再执行其它线程
*/
public class SemaphoreSample {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool();
Semaphore semaphore = new Semaphore(5);//定义5个信号量
for (int i = 1; i <= 20; i++) {
final int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
//尝试获取一次信号量,6秒钟内获取到返回true,否则返回false
if (semaphore.tryAcquire(6,TimeUnit.SECONDS)) {
play();
semaphore.release();//执行完成后,释放这个信号量
} else {
System.out.println(Thread.currentThread().getName() + ":对不起服务器已满,请稍后再试");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
//关闭线程池
threadPool.shutdown();
}
运行结果
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-4:获得进入服务器资格
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-3:获得进入服务器资格
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-6:获得进入服务器资格
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-2:获得进入服务器资格
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-1:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-4:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-6:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-1:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-3:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-2:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-5:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-7:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-11:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-15:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-10:获得进入服务器资格
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-5:退出服务器
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-11:退出服务器
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-7:退出服务器
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-10:退出服务器
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-15:退出服务器
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-8:获得进入服务器资格
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-12:获得进入服务器资格
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-14:获得进入服务器资格
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-13:获得进入服务器资格
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-9:获得进入服务器资格
pool-1-thread-17:对不起服务器已满,请稍后再试
pool-1-thread-20:对不起服务器已满,请稍后再试
pool-1-thread-19:对不起服务器已满,请稍后再试
pool-1-thread-18:对不起服务器已满,请稍后再试
pool-1-thread-16:对不起服务器已满,请稍后再试
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-8:退出服务器
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-12:退出服务器
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-14:退出服务器
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-13:退出服务器
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-9:退出服务器
3. JUC之CyclicBarrier循环屏障
/**
* CyclicBarrier循环屏障
* 是一个同步工具类,它允许一组线程互相等待,知道到达某个公共屏障点
* 与CountDawnLatch不同的是该barrier在释放等待线程后可以重用
*/
public class CyclicBarrierSample {
//定义屏障点 5个线程
private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i = 1; i <= 10; i++) {
final int index = i;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.execute(new Runnable() {
@Override
public void run() {
go();
}
});
}
//关闭线程池
threadPool.shutdown();
}
private static void go() {
System.out.println(Thread.currentThread().getName() + " : 准备就绪");
try {
cyclicBarrier.await();//设置屏障点,当累计5个线程都准备好后,才运行后面的代码
System.out.println(Thread.currentThread().getName() + " : 开始运行");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
运行结果
pool-1-thread-1 : 准备就绪
pool-1-thread-2 : 准备就绪
pool-1-thread-3 : 准备就绪
pool-1-thread-4 : 准备就绪
pool-1-thread-5 : 准备就绪
pool-1-thread-5 : 开始运行
pool-1-thread-1 : 开始运行
pool-1-thread-3 : 开始运行
pool-1-thread-2 : 开始运行
pool-1-thread-4 : 开始运行
pool-1-thread-4 : 准备就绪
pool-1-thread-2 : 准备就绪
pool-1-thread-3 : 准备就绪
pool-1-thread-1 : 准备就绪
pool-1-thread-5 : 准备就绪
pool-1-thread-5 : 开始运行
pool-1-thread-4 : 开始运行
pool-1-thread-2 : 开始运行
pool-1-thread-1 : 开始运行
pool-1-thread-3 : 开始运行
4. JUC之Conditon线程等待与唤醒
/**
* Codintion线程的等待与唤醒
* 需要配合ReentrantLock 重入锁使用
*/
public abstract class ConditonSample {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
condition1.await();
Thread.sleep(1000);
System.out.println("粒粒皆辛苦");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {//重入锁需要手动解锁
lock.unlock();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
condition2.await();
Thread.sleep(1000);
System.out.println("谁知盘中餐");
condition1.signal();//唤醒c1
} catch (InterruptedException e) {
e.printStackTrace();
}finally {//重入锁需要手动解锁
lock.unlock();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
condition3.await();
Thread.sleep(1000);
System.out.println("汗滴禾下土");
condition2.signal();//唤醒c2
}catch (Exception e){
e.printStackTrace();
}finally {//重入锁需要手动解锁
lock.unlock();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
Thread.sleep(1000);
System.out.println("锄禾日当午");
condition3.signal(); //唤醒c3
}catch (Exception e){
e.printStackTrace();
}finally {//重入锁需要手动解锁
lock.unlock();
}
}
}).start();
}
}
运行结果
锄禾日当午
汗滴禾下土
谁知盘中餐
粒粒皆辛苦
5. JUC之Callable_Future
public class Callable_Future_Sample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
//打印1000以内的质数
for (int i = 2; i <= 1000; i++) {
Computor computor = new Computor();
computor.setNum(i);
//将computor对象提交给线程池,如果有空闲线程立即执行里面的call方法
//Future是对用于计算的线程进行监听,应为计算时在其它线程中执行的,所以这个返回的结果时异步的
Future submitResult = executorService.submit(computor);
try {
//用于获取返回值,如果线程池内部的call方法没有执行完成,则进入等待状态,知道计算完成
Boolean r = submitResult.get();
if (r == true) {
System.out.println(computor.getNum());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
//关闭线程池
executorService.shutdown();
}
}
class Computor implements Callable {
private Integer num;
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
@Override
public Boolean call() throws Exception {
boolean isprime = true;
for (int i = 2; i < num; i++) {
if (num % i == 0) {
isprime = false;
break;
}
}
return isprime;
}
}
运行结果
2
3
5
7
11
13
17
19