一,Condition

一个场景,两个线程数数,同时启动两个线程,线程A数1、2、3,然后线程B数4、5、6,最后线程A数7、8、9,程序结束,这涉及到线程之间的通信。

public classConditionTest {static classNumberWrapper {public int value = 1;

}public static voidmain(String[] args) {//初始化可重入锁

final Lock lock = newReentrantLock();//第一个条件当屏幕上输出到3

final Condition reachThreeCondition =lock.newCondition();//第二个条件当屏幕上输出到6

final Condition reachSixCondition =lock.newCondition();//NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final//注意这里不要用Integer, Integer 是不可变对象

final NumberWrapper num = newNumberWrapper();//初始化A线程

Thread threadA = new Thread(newRunnable() {

@Overridepublic voidrun() {//需要先获得锁

lock.lock();

System.out.println("ThreadA获得lock");try{

System.out.println("threadA start write");//A线程先输出前3个数

while (num.value <= 3) {

System.out.println(num.value);

num.value++;

}//输出到3时要signal,告诉B线程可以开始了

reachThreeCondition.signal();

}finally{

lock.unlock();

System.out.println("ThreadA释放lock");

}

lock.lock();try{//等待输出6的条件

System.out.println("ThreadA获得lock");

reachSixCondition.await();

System.out.println("threadA start write");//输出剩余数字

while (num.value <= 9) {

System.out.println(num.value);

num.value++;

}

}catch(InterruptedException e) {

e.printStackTrace();

}finally{

lock.unlock();

System.out.println("ThreadA释放lock");

}

}

});

Thread threadB= new Thread(newRunnable() {

@Overridepublic voidrun() {try{

lock.lock();

System.out.println("ThreadB获得lock");

Thread.sleep(5000);//是await方法释放了锁

while (num.value <= 3) {//等待3输出完毕的信号

reachThreeCondition.await();

}

}catch(InterruptedException e) {

e.printStackTrace();

}finally{

lock.unlock();

System.out.println("ThreadB释放lock");

}try{

lock.lock();

System.out.println("ThreadB获得lock");//已经收到信号,开始输出4,5,6

System.out.println("threadB start write");while (num.value <= 6) {

System.out.println(num.value);

num.value++;

}//4,5,6输出完毕,告诉A线程6输出完了

reachSixCondition.signal();

}finally{

lock.unlock();

System.out.println("ThreadB释放lock");

}

}

});//启动两个线程

threadB.start();

threadA.start();

}

}

创建方式:通过Lock创建,Lock.newCondition();

常用方法:

await():阻塞,直到相同的Condition调用了signal方法。

signal():通知。

总结:Condition必须与Lock一起使用(wait()、notify()必须与synchronized一起使用,否则运行会报错java.lang.IllegalMonitorStateException),相比于wait与notify更加的灵活,可以设置各种情形,如上例中的到达3和到达6两个条件。

二,CountDownLatch

直接上代码:

public classCountDownLatchTest {public static voidmain(String[] args) {final CountDownLatch c = new CountDownLatch(3);//总数3

Thread t1 = new Thread(newRunnable(){

@Overridepublic voidrun() {try{

System.out.println("开始等");

c.await();//阻塞,等待countDown,当countDown到0就执行后面的完事了

System.out.println("完事");

}catch(InterruptedException e) {

e.printStackTrace();

}

}

});

Thread t2= new Thread(newRunnable(){

@Overridepublic voidrun() {for(int i=3;i>0;i--){

c.countDown();//减1

}

}

});

t1.start();

t2.start();

}

}

创建方式:直接创建,new CountDownLatch(int num);

常用方法:

await():阻塞,直到countDown方法被执行了num次。

countDown():减

总结:适用于一个线程等待其他线程的情景。

三,CyclicBarrier

通过代码思考一下与CountDownLatch的区别。

public classMainMission {privateCyclicBarrier barrier;private final static int threadCounts = 5;public voidrunMission() {

ExecutorService exec=Executors.newFixedThreadPool(threadCounts);//new 的时候要传入数字,我发现,这个类似semaphore,如果位置不足,线程会抢位置。数字要是threadCounts+1为主线程留一个位子,但实际测试中发现,只要等于threadCount就可以

barrier=new CyclicBarrier(threadCounts+1);for(int i=0;i<5;i++){

exec.execute(newMission(barrier));

}try{

barrier.await();

}catch(InterruptedException e) {

e.printStackTrace();

}catch(BrokenBarrierException e) {

e.printStackTrace();

}try{

Thread.sleep(1);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("所有任务都执行完了");

exec.shutdown();//如果不关闭,程序一直处于运行状态

}public static voidmain(String[] args) {

MainMission m= newMainMission();

m.runMission();

}

}class Mission implementsRunnable{privateCyclicBarrier barrier;publicMission(CyclicBarrier barrier){this.barrier =barrier;

}

@Overridepublic voidrun() {

System.out.println(Thread.currentThread().getName()+"开始执行任务");try{int sleepSecond = new Random().nextInt(10)*1000;

System.out.println(Thread.currentThread().getName()+"要执行"+sleepSecond+"秒任务");

Thread.sleep(sleepSecond);

}catch(InterruptedException e) {

e.printStackTrace();

}try{

barrier.await();

}catch(InterruptedException e) {

e.printStackTrace();

}catch(BrokenBarrierException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"执行完毕");

}

}

创建方式:直接创建,new CyclicBarrier(int num);

常用方法:

await():阻塞,直到阻塞的线程数量达到num个。

总结:想想一下百米跑,所有运动员都就位之后才会发令起跑,线程调用await意味着说,我准备好了。

四,Semaphore

下面是一个上厕所的例子,厕所位置有限,想用得排队了。实现使用的就是信号量,可以看出信号量可以用来做限流。

public class MySemaphore implementsRunnable{

Semaphore position;private intid;public MySemaphore(inti,Semaphore s){this.id=i;this.position=s;

}

@Overridepublic voidrun() {try{if(position.availablePermits()>0){

System.out.println("顾客["+this.id+"]进入厕所,有空位");

}else{

System.out.println("顾客["+this.id+"]进入厕所,没空位,排队");

}

position.acquire();//只有在acquire之后才能真正的获得了position

System.out.println("#########顾客["+this.id+"]获得坑位");

Thread.sleep((int)(Math.random()*100000));

System.out.println("@@@@@@@@@顾客["+this.id+"]使用完毕");

position.release();

}catch(Exception e){

e.printStackTrace();

}

}public static voidmain(String args[]){

ExecutorService list=Executors.newCachedThreadPool();

Semaphore position=new Semaphore(2);for(int i=0;i<10;i++){

list.submit(new MySemaphore(i+1,position));

}

list.shutdown();

position.acquireUninterruptibly(2);

System.out.println("使用完毕,需要清扫了");

position.release(2);

}

}

创建方式:直接创建,new Semaphore(int num);

常用方法:

availablePermits():看现在可用的信号量。

acquire():尝试获取一个位置,如果获取不到则阻塞。

release():释放位置。

acquireUninterruptibly(int num):尝试获取num个许可,如果没有足够的许可则阻塞,一直阻塞到有足够的许可释放出来。调用这个方法的线程具有优先获取许可的权利。如果调用线程被interrupted,该线程并不会被打断,它会继续阻塞等待许可。

总结:抢位置。

五,ReentrantLock

创建方式:

new ReentrantLock(); 此种创建方式会创建出一个非公平锁。

new ReentrantLock(true); 此种方式会创建出一个公平锁。

非公平锁:当锁处于无线程占有的状态,此时其他线程和在队列中等待的线程都可以抢占该锁。

公平锁:当锁处于无线程占有的状态,在其他线程抢占该锁的时候,都需要先进入队列中等待。

tryLock()方法:尝试去获取锁,如果没有获取到直接返回,不等待。

六,ReentrantReadWriteLock

创建方式:new ReentrantReadWriteLock();

常用方法:

readLock().lock();写锁

writeLock().lock();读锁

readLock().unlock();解锁

writeLock().unlock();解锁

总结:

* 如果目前是读锁,其他读锁也可以进请求,写锁不能进。

* 如果目前是写锁,那么其他所有的锁都不可以进。

*适用于读多写少的情况,如果是写多读少用ReentrantLock。

七,Callable接口

*Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取结果;当不调用此方法时,主线程不会阻塞!

与Runnable对比:

1.Callable可以有返回值,Runnable没有

2.Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

八,线程池

提供的线程池有几种:

//有数量限制的线程池

ExecutorService service=Executors.newFixedThreadPool(4);

//没有数量限制的线程池

ExecutorService service=Executors.newCachedThreadPool();

//单线程池

ExecutorService service=Executors.newSingleThreadExecutor();

他们都是通过下面这个线程池实现的

有数量线程池的实现方式

public static ExecutorService newFixedThreadPool(intnThreads) {return newThreadPoolExecutor(nThreads/*核心线程数*/, nThreads/*最高线程数*/,0L/*高出核心线程数的线程最高存活时间*/, TimeUnit.MILLISECONDS/*高出核心线程数的线程最高存活时间单位*/,new LinkedBlockingQueue()/*任务队列*/);

猜一猜剩下的两种线程池是怎么实现的。如果想自己实现,可以自己new

java.util 常见_Java基础知识-java.util.concurrent包下常见类的使用相关推荐

  1. java的技术定义_java基础知识——Java的定义,特点和技术平台

    (作者声明:对于Java编程语言,很多人只知道怎么用,却对其了解甚少.我也是其中一员.所以菜鸟的我,去查询了教科书以及大神的总结,主要参考了<Java核心技术>这本神作.现在分享给大家!) ...

  2. java e次方_java基础知识

    一.java的简介 1.后台开发语言.跨平台,安全性高.面向对象 二.java基础 1.类是java中最小编写代码的单元 2.语句要分号结束 3.括号成对出现 4.运行原理--从上往下 三.注释:代码 ...

  3. java.io.file()_JAVA基础知识之IO-File类

    File类介绍 File是java.io包下面的一个类,代表与平台无关的文件或者目录.JAVA中,无论文件还是目录,都可以看作File类的一个对象.File类能对文件或目录新建,删除,获取属性等操作, ...

  4. java class 字符串_java基础知识四 math类 字符 字符串 控制台输入输出 StringBuilder与StringBuffer...

    第四章:数学函数.字符和字符串 math类 Math是final类:在java.lang.Math中,所有数学函数都是静态方法 在一个java程序中,java.lang包中的所有类是隐式导入的. 三角 ...

  5. java 集合数据类型_Java基础知识(数据类型和集合)

    一.数据类型 包装类型 包装类型是对基本数据类型不足之处的补充. 基本数据类型的传递方式是值传递,而包装类型是引用传递,同时提供了很多数据类型间转换的方法. Java1.5 以后可以自动装箱和拆箱 二 ...

  6. java io 对象_JAVA基础知识之IO——对象序列化

    对象序列化 Java对象序列化(Serialize)是指将Java对象写入IO流,反序列化(Deserilize)则是从IO流中恢复该Java对象. 对象序列化将程序运行时内存中的对象以字节码的方式保 ...

  7. java 计算反码_java基础知识-原码、反码、补码、运算符

    一.原码.反码.补码 原码 一个数转化成二进制. 用最高位来表示正负,最高位为0表示正数,最高位为1表示负数. 例如: short i=5: 因为在java里short占2个字节转化成二进制就是 00 ...

  8. java表达式语句_Java基础知识笔记第三章:运算符表达式语句

    算术运算符与表达式 操作符描述例子 + 加法 - 相加运算符两侧的值 A + B 等于 30 - 减法 - 左操作数减去右操作数 A – B 等于 -10 * 乘法 - 相乘操作符两侧的值 A * B ...

  9. java操作符重载_Java基础知识-操作符重载

    java操作符重载 String str1 = "hello"; String str2 = str1 + " world"; System.out.print ...

最新文章

  1. 条款22: 尽量用“传引用”而不用“传值”
  2. 女程序猿2014总结(修改)
  3. 操作系统的起源|开源运动的兴起
  4. e2140服务器性能,4000 还是E2140?两大人气CPU对决
  5. 【Docker】Docker java shell ssh
  6. 分享一款好看的城市选择器
  7. non linear processor
  8. 【CCCC】L2-002 链表去重 (25分),,把一个链表拆成两个
  9. C# winform如何设置ListBox背景图或者透明背景及边框色
  10. Linux部署-elasticsearch7.6.1
  11. c语言逻辑运算符用法大全,C语言逻辑运算符介绍和示例
  12. 移动铁通宽带上网设置教程
  13. Learning Git Branching
  14. 微信扫码点餐小程序怎么做,一步步教你
  15. 低分辨率人脸识别(LRFR)相关文章整理——(待更)
  16. win10内存占用率过高怎么办_DNF:WIN10玩DNF卡顿,内存占用过高的解决方法
  17. assert()详解
  18. 集成电路(芯片 ic chip)详解
  19. python猜单词游戏_python实现猜单词游戏
  20. 在我的世界中用 python 编程

热门文章

  1. C语言入门题-计算到任意日期的总天数
  2. 计算机用户名密码策略,设置域用户帐户密码策略
  3. mysql 一对多映射_mybatis关系映射之一对多和多对一
  4. gpio复用 海思_实现海思平台GPIO驱动
  5. 给JBoss种蛊分析
  6. MySQL临时表的操作使用
  7. 牛客网(剑指offer) 第七题 斐波那契数列
  8. [Python图像处理] 三十一.图像点运算处理两万字详细总结(灰度化处理、阈值化处理)
  9. [网络安全自学篇] 三十.文件上传漏洞、编辑器漏洞和IIS高版本漏洞及防御(三)
  10. 【数据结构与算法】之深入解析二叉树的算法实现和递归套路深度实践