转载自https://blog.csdn.net/Veson__/article/details/53898890

在做一款app的时候,用到了一个异步执行的api,而我想要的是同步执行,查了一些资料,对几种情况下的线程同步做一下总结。

一、共享资源的同步

问题:当一个资源被多个线程访问会发生错误,只能允许一个线程访问时。

1.syschronized实现

使用syschonized关键字可对某个块或者方法进行限制访问,即当一个线程获得块或者方法的访问权后,其他线程将不能访问。

[java] view plaincopy
  1. public class synchronize_test implements Runnable{
  2. int num1 = 10;
  3. int num2 = 10;
  4. int num3 = 10;
  5. public void synchonized_test() {
  6. synchronized(this) {
  7. while(num1 > 0) { //只有得到锁的线程才能访问
  8. System.out.println(Thread.currentThread().getName() + "访问num1=" + num1--);
  9. }
  10. }
  11. synchronized(this) { //只有得到锁的线程才能访问,即使它还没有开始访问这儿,因为同步锁的作用对象是对象中的所有同步块
  12. while(num2 > 0) {
  13. System.out.println(Thread.currentThread().getName() + "访问num2=" + num2--);
  14. }
  15. }
  16. while(num3 > 0) { //未得到锁的线程可访问此资源(非同步块)
  17. System.out.println(Thread.currentThread().getName() + "访问num3=" + num3--);
  18. }
  19. }
  20. @Override
  21. public void run() {
  22. synchonized_test();
  23. }
  24. public static void main(String[] args) {
  25. synchronize_test sys = new synchronize_test();
  26. Thread t1 = new Thread(sys);
  27. Thread t2 = new Thread(sys);
  28. t1.start();
  29. t2.start();
  30. }
  31. }

当使用sychronized修饰某个方法(非static)时,作用对象将是这个方法所属的对象,与同步块同理。而如果synchronized修饰的是static方法或变量时,作

用对象将是static所在的类而非某个对象,因为static方法不属于任何一个对象,而是属于类。

2.Lock实现

可以看出,syschronized的作用的是对象或者类,这显然不太灵活,而Lock则比其更加灵活一些。

[java] view plaincopy
  1. public class Lock_Test implements Runnable{
  2. int num1 = 10;
  3. int num2 = 10;
  4. Lock lock1 = new ReentrantLock();
  5. Lock lock2 = new ReentrantLock();
  6. public void synchonized_test() {
  7. lock1.lock(); //获得lock1
  8. try {
  9. while(num1 > 0) { //只有得到锁的线程才能访问
  10. System.out.println(Thread.currentThread().getName() + "访问num1=" + num1--);
  11. }
  12. } finally {
  13. lock1.unlock();
  14. }
  15. lock2.lock();//获得lock2
  16. try {
  17. while(num2 > 0) {
  18. System.out.println(Thread.currentThread().getName() + "访问num2=" + num2--);
  19. }
  20. } finally {
  21. //在finally中解锁以防死锁
  22. lock2.unlock(); //解锁
  23. }
  24. }
  25. @Override
  26. public void run() {
  27. synchonized_test();
  28. }
  29. public static void main(String[] args) {
  30. Lock_Test lt = new Lock_Test();
  31. Thread t1 = new Thread(lt);
  32. Thread t2 = new Thread(lt);
  33. t1.start();
  34. t2.start();
  35. }
  36. }

这里使用的是ReentrantLock,另外还有ReadWriteLock。

ReentranLock的优点(摘自:https://github.com/pzxwhc/MineKnowContainer/issues/16)

lock在获取锁的过程可以被中断。

lock可以尝试获取锁,如果锁被其他线程持有,则返回 false,不会使当前线程休眠。

lock在尝试获取锁的时候,传入一个时间参数,如果在这个时间范围内,没有获得锁,那么就是终止请求。

synchronized 会自动释放锁,lock 则不会自动释放锁。

二、异步转同步

问题:某些API是异步的,而我们想让其同步。如:A、B两个方法异步执行,由于某些需求,想让A方法执行完之后再执行B方法。

1.CountDownLatch解决

使用CountDownLatch可以实现同步,它好比计数器,在实例CountDownLatch对象的时候传入数字,每使用一次 .countDown() 方法计数减1,当数字减到0时, .await()方法后的代码将可以执行,未到0之前将一直阻塞等待。

[java] view plaincopy
  1. import java.util.concurrent.CountDownLatch;
  2. public class CountDownLatch_test implements Runnable{
  3. private Integer num = null;
  4. private static CountDownLatch latch;
  5. public void setNumber() {
  6. num = 1;
  7. }
  8. public int getNumber() {
  9. return this.num;
  10. }
  11. @Override
  12. public void run() {
  13. if(Thread.currentThread().getName().equals("Thread-0")) { //t2线程
  14. try {
  15. Thread.sleep(5000);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. this.setNumber();
  20. latch.countDown(); //计数减1
  21. }
  22. else if(Thread.currentThread().getName().equals("Thread-1")){ //t1线程
  23. try {
  24. latch.await(); //阻塞等待计数为0
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. System.out.println("num = " + this.getNumber());
  29. }
  30. }
  31. public static void main(String[] args) {
  32. CountDownLatch_test c = new CountDownLatch_test();
  33. latch = new CountDownLatch(1);
  34. Thread t1 = new Thread(c);
  35. Thread t2 = new Thread(c);
  36. t1.start();
  37. t2.start();
  38. }
  39. }

如代码所示,t1线程获得num的值,t2线程给num赋值,显然t2需要在t1之前执行结束,而t2执行的时间却比t1长,故使用CountDown对t1进行阻塞等待t2完成。

此外,也可以给await(设置参数),到达一定时间计数未变为0也可执行。

********其他方法待学习*******

java 总结几种线程异步转同步的方法相关推荐

  1. 请回答一下Java中有几种线程池及实现过程?

    请回答一下Java中有几种线程池及实现过程? 1.newFixedThreadPool创建一个指定工作线程数量的线程池.每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将 ...

  2. java布尔类型比较器_浅谈Java中几种常见的比较器的实现方法

    在java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题. 通常对象之间的比较可以从两个方面去看: 第一个方面:对象的地址是否一样,也就是是否引用自同一个对象.这种方式可以直接使用& ...

  3. Java ExecutorService四种线程池的例子与说明

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() {@Overridepublic void run() {// ...

  4. java中四种线程池及poolSize、corePoolSize、maximumPoolSize

    目录 ThreadPoolExecutor重要参数 poolSize.corePoolSize.maximumPoolSize 四种线程池 newFixedThreadPool newCachedTh ...

  5. java中四种线程池的区别

    本文按: 一. 线程池的使用 二. 几种线程池的区别 三. 如何合理配置线程池 一.线程池的使用 在Java中,通常使用Executors 获取线程池.常用的线程池有以下几种: (1)CachedTh ...

  6. java 线程工厂_Java并发编程:Java的四种线程池的使用,以及自定义线程工厂

    引言 通过前面的文章,我们学习了Executor框架中的核心类ThreadPoolExecutor ,对于线程池的核心调度机制有了一定的了解,并且成功使用ThreadPoolExecutor 创建了线 ...

  7. Linux 多线程 - 线程异步与同步机制

    I. 同步机制 线程间的同步机制主要包括三个: 互斥锁: 以排他的方式,防止共享资源被并发访问: 互斥锁为二元变量, 状态为0-开锁.1-上锁; 开锁必须由上锁的线程执行,不受其它线程干扰. 条件变量 ...

  8. java之阻塞非阻塞异步和同步

    概念介绍 同步: 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回. 异步: 异步的概念和同步相对.当一个异步过程调用发出后,调用者不能立刻得到结果.实际处理这个调用的部件在完成 ...

  9. Java中四种线程池介绍

    个人资源与分享网站:http://xiaocaoshare.com/ Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而是一个执行线程的工具.真正的线 ...

最新文章

  1. linux ssh 报错 Failed to start OpenSSH Server daemon
  2. Linux监控服务命令
  3. Python scrapy爬取京东,百度百科出现乱码,解决方案
  4. jscript换行等特殊字符
  5. c语言数字储存于变量,用C语言写中文数字字符串转数值变量
  6. UVA - 101:The Blocks Problem
  7. qt显示rgba8888 如何改 frame_Qt开源作品17-IP地址输入控件
  8. SQLServer引擎优化顾问
  9. 转行前端很迷茫,该怎么办?
  10. 【李宏毅2020 ML/DL】P67-72 Anomaly Detection
  11. Apache OpenNLP(二)
  12. 转帖:MySql日期格式化
  13. 毛氏生产:经常集体文化娱乐活动,有何利弊
  14. 阿里云磐久服务器M系列研发之路
  15. eclipse字体大小怎么设置
  16. mac删除的文件还能找回吗
  17. 分布式光伏系列:分布式光伏电站 运行与维护方案一览(zz)
  18. 全网功能最全的无水印短视频提取工具
  19. JavaScript trim 实现(去除字符串左侧左侧首尾空格)
  20. PHP getimagesize(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL rou

热门文章

  1. socket 通信关于bind那点事
  2. 数据结构与算法 | 二叉树的实现
  3. selenium的使用教程3
  4. 面试官让我说出2种@Transactional注解的失效场景,我一口气给他说了六种
  5. 某大佬的20+公司面试题总结和自己的补充
  6. MySQL(二)InnoDB的内存结构和特性
  7. TCP/IP协议精华指南pdf发布
  8. 千万不要在深夜提交代码
  9. JAVA 泛型中的通配符 T,E,K,V,?
  10. 七牛云徐晶:低延迟互动时代看好WebRTC和SRT