java线程同步工具类总结

来源:互联网 发布:javascript数字格式化 编辑:程序博客网 时间:2024/06/01 10:21

本文可作为传智播客《张孝祥-Java多线程与并发库高级应用》的学习笔记。

Semaphore

这个东西和之前的synchronized干的事差不多。
synchronized保证了,我管理的那部分代码同一时刻只有一个线程能访问
Semaphore保证了,我管理的那部分代码同一时刻最多可以有n个线程访问

import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;  import java.util.concurrent.Semaphore;  public class SemaphoreTest {      public static void main(String[] args) {          ExecutorService service = Executors.newCachedThreadPool();          final  Semaphore sp = new Semaphore(3);          for(int i=0;i<10;i++){              Runnable runnable = new Runnable(){                      public void run(){                      try {                          sp.acquire();                      } catch (InterruptedException e1) {                          e1.printStackTrace();                      }                      System.out.println("线程" + Thread.currentThread().getName() +                               "进入,当前已有" + (3-sp.availablePermits()) + "个并发");                      try {                          Thread.sleep((long)(Math.random()*10000));                      } catch (InterruptedException e) {                          e.printStackTrace();                      }                      System.out.println("线程" + Thread.currentThread().getName() +                               "即将离开");                                          sp.release();                      //下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元                      System.out.println("线程" + Thread.currentThread().getName() +                               "已离开,当前已有" + (3-sp.availablePermits()) + "个并发");                                      }              };              service.execute(runnable);                    }      }  }  

CycleBarrier

CycleBarrier 能做到让n个线程互相等待,当n个线程都做到某一步后,再继续下一步。
例如下面的例子,5个人去旅游,设置abc三个中途节点,所有人都到达a之后在继续走向b,所有人都到达b,然后才继续走向c。

import java.util.concurrent.CyclicBarrier;  import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;  public class CyclicBarrierTest {      public static void main(String[] args) {          ExecutorService service = Executors.newCachedThreadPool();          final  CyclicBarrier cb = new CyclicBarrier(3);          for(int i=0;i<3;i++){              Runnable runnable = new Runnable(){                      public void run(){                      try {                          Thread.sleep((long)(Math.random()*10000));                            System.out.println("线程" + Thread.currentThread().getName() +                                   "即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                                                 cb.await();                          Thread.sleep((long)(Math.random()*10000));                            System.out.println("线程" + Thread.currentThread().getName() +                                   "即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                          cb.await();                           Thread.sleep((long)(Math.random()*10000));                            System.out.println("线程" + Thread.currentThread().getName() +                                   "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                                               cb.await();                                           } catch (Exception e) {                          e.printStackTrace();                      }                                 }              };              service.execute(runnable);          }          service.shutdown();      }  }  

CountDownLatch

它保证了什么功能呢?其实和CycliBarrier也类似。
看下面这个图

这就是CycleBarrier,线程自己管理自己,大家看到人都到齐了,才继续走。
这个是CountDownLatch,由他人来协调进度。

例如跑步的时候,有个裁判,等所有的人都到齐了,他吹哨,然后大家开始跑,等所有人都跑完了,他才公布成绩。

import java.util.concurrent.CountDownLatch;  import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;  public class CountdownLatchTest {      public static void main(String[] args) {          ExecutorService service = Executors.newCachedThreadPool();          final CountDownLatch cdOrder = new CountDownLatch(1);          final CountDownLatch cdAnswer = new CountDownLatch(3);                for(int i=0;i<3;i++){              Runnable runnable = new Runnable(){                      public void run(){                      try {                          System.out.println("线程" + Thread.currentThread().getName() +                                   "正准备接受命令");                                               cdOrder.await();                          System.out.println("线程" + Thread.currentThread().getName() +                           "已接受命令");                                                         Thread.sleep((long)(Math.random()*10000));                            System.out.println("线程" + Thread.currentThread().getName() +                                   "回应命令处理结果");                                                  cdAnswer.countDown();                                             } catch (Exception e) {                          e.printStackTrace();                      }                                 }              };              service.execute(runnable);          }                 try {              Thread.sleep((long)(Math.random()*10000));              System.out.println("线程" + Thread.currentThread().getName() +                       "即将发布命令");                                    cdOrder.countDown();              System.out.println("线程" + Thread.currentThread().getName() +               "已发送命令,正在等待结果");                  cdAnswer.await();              System.out.println("线程" + Thread.currentThread().getName() +               "已收到所有响应结果");             } catch (Exception e) {              e.printStackTrace();          }                         service.shutdown();      }  }  

CountDownLatch里面有个计数器,初始值就是new countdownlatch时传入的
wait方法会一直等待,直到计数器的值变为0
coutdown方法可以让计数器的值减一

Exchange

A线程有数据1,它需要与B线程的数据2做交换
B线程有数据2,它需要与A线程的数据1做交换
那么什么时候交换呢?得等AB都做好准备才行。

import java.util.concurrent.Exchanger;  import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;  public class ExchangerTest {      public static void main(String[] args) {          ExecutorService service = Executors.newCachedThreadPool();          final Exchanger<String> exchanger = new Exchanger<String>();          service.execute(new Runnable(){              public void run() {                  try {                                     String data1 = "zxx";                      System.out.println("线程" + Thread.currentThread().getName() +                       "正在把数据" + data1 +"换出去");                      Thread.sleep((long)(Math.random()*10000));                      String data2 = (String)exchanger.exchange(data1);                      System.out.println("线程" + Thread.currentThread().getName() +                       "换回的数据为" + data2);                  }catch(Exception e){                  }              }             });          service.execute(new Runnable(){              public void run() {                  try {                                     String data1 = "lhm";                      System.out.println("线程" + Thread.currentThread().getName() +                       "正在把数据" + data1 +"换出去");                      Thread.sleep((long)(Math.random()*10000));                                        String data2 = (String)exchanger.exchange(data1);                      System.out.println("线程" + Thread.currentThread().getName() +                       "换回的数据为" + data2);                  }catch(Exception e){                  }                             }             });           }  }  
原创粉丝点击