1.新知识普及
1 2. Semaphore工具类的使用案例 2 package com.java5.thread.newSkill; 3 4 import java.util.concurrent.ExecutorService; 5 import java.util.concurrent.Executors; 6 import java.util.concurrent.Semaphore; 7 8 /** 9 * Semaphore工具类的使用案例 10 * 跟互斥锁有点相似,只是互斥锁只有一把,信号灯可以有多个 11 * Semaphore:信号灯 12 */ 13 public class SemaphoreTest { 14 15 16 public static void main(String[] args) { 17 18 ExecutorService service = Executors.newCachedThreadPool(); 19 // 20 final Semaphore sp = new Semaphore(3); 21 for(int i=0;i<10;i++){ 22 Runnable runnable = new Runnable() { 23 24 @Override 25 public void run() { 26 try { 27 //acquire:获得;下面方法是获取信号灯 28 sp.acquire(); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 //availablePermits():可以获得的许可 33 System.out.println("线程 "+Thread.currentThread().getName()+" 进入,当前已有 "+(3-sp.availablePermits())+" 个并发!"); 34 35 try { 36 Thread.sleep((long)Math.random()*10000); 37 } catch (InterruptedException e) { 38 e.printStackTrace(); 39 } 40 System.out.println("线程 "+Thread.currentThread().getName()+" 即将离开!"); 41 //释放信号灯 42 sp.release(); 43 //下面代码有时候执行不准确 44 System.out.println("线程 "+Thread.currentThread().getName()+" 离开,当前已有 "+(3-sp.availablePermits())+" 个并发!"); 45 46 } 47 }; 48 service.execute(runnable); 49 } 50 51 } 52 } 53 54 /* 55 * 运行结果: 56 线程 pool-1-thread-1 进入,当前已有 1 个并发! 57 线程 pool-1-thread-1 即将离开! 58 线程 pool-1-thread-1 离开,当前已有 0 个并发! 59 线程 pool-1-thread-1 进入,当前已有 1 个并发! 60 线程 pool-1-thread-1 即将离开! 61 线程 pool-1-thread-1 离开,当前已有 0 个并发! 62 线程 pool-1-thread-1 进入,当前已有 1 个并发! 63 线程 pool-1-thread-3 进入,当前已有 2 个并发! 64 线程 pool-1-thread-1 即将离开! 65 线程 pool-1-thread-1 离开,当前已有 1 个并发! 66 线程 pool-1-thread-3 即将离开! 67 线程 pool-1-thread-3 离开,当前已有 0 个并发! 68 线程 pool-1-thread-3 进入,当前已有 1 个并发! 69 线程 pool-1-thread-1 进入,当前已有 2 个并发! 70 线程 pool-1-thread-3 即将离开! 71 线程 pool-1-thread-3 离开,当前已有 1 个并发! 72 线程 pool-1-thread-1 即将离开! 73 线程 pool-1-thread-1 离开,当前已有 0 个并发! 74 线程 pool-1-thread-1 进入,当前已有 1 个并发! 75 线程 pool-1-thread-5 进入,当前已有 2 个并发! 76 线程 pool-1-thread-1 即将离开! 77 线程 pool-1-thread-1 离开,当前已有 1 个并发! 78 线程 pool-1-thread-5 即将离开! 79 线程 pool-1-thread-5 离开,当前已有 0 个并发! 80 线程 pool-1-thread-2 进入,当前已有 1 个并发! 81 线程 pool-1-thread-2 即将离开! 82 线程 pool-1-thread-2 离开,当前已有 0 个并发! 83 线程 pool-1-thread-4 进入,当前已有 1 个并发! 84 线程 pool-1-thread-4 即将离开! 85 线程 pool-1-thread-4 离开,当前已有 0 个并发! 86 87 */ 88 3. CyclicBarrier工具类的使用案例 89 package com.java5.thread.newSkill; 90 91 import java.util.concurrent.CyclicBarrier; 92 import java.util.concurrent.ExecutorService; 93 import java.util.concurrent.Executors; 94 95 /** 96 * CyclicBarrier工具类的使用案例 97 * 应用场景:各个线程彼此等待,到齐后集体出发 98 * cyclic:循环的,周期性的 99 * barrier:障碍物,屏障 100 */ 101 public class CyclicBarrierTest { 102 103 public static void main(String[] args) { 104 105 ExecutorService service = Executors.newCachedThreadPool(); 106 final CyclicBarrier cb = new CyclicBarrier(3); 107 for(int i=0;i<3;i++){ 108 Runnable runnable= new Runnable() { 109 110 @Override 111 public void run() { 112 try { 113 Thread.sleep((long)Math.random()*10000); 114 //cb.getNumberWaiting()+1;是因为该方法获取的数量是从0开始的 115 System.out.println("线程 "+ Thread.currentThread().getName()+" 即将到达集合地点1,当前已有 "+(cb.getNumberWaiting()+1)+"已经到达;"+(cb.getNumberWaiting()==2?"都到齐了,继续走啊!":"正在等候!")); 116 //想在什么地方集合就在什么地方await()等待 117 cb.await(); 118 119 Thread.sleep((long)Math.random()*10000); 120 System.out.println("线程 "+ Thread.currentThread().getName()+" 即将到达集合地点2,当前已有 "+(cb.getNumberWaiting()+1)+"已经到达;"+(cb.getNumberWaiting()==2?"都到齐了,继续走啊!":"正在等候!")); 121 122 cb.await(); 123 124 Thread.sleep((long)Math.random()*10000); 125 System.out.println("线程 "+ Thread.currentThread().getName()+" 即将到达集合地点3,当前已有 "+(cb.getNumberWaiting()+1)+"已经到达;"+(cb.getNumberWaiting()==2?"都到齐了,继续走啊!":"正在等候!")); 126 127 cb.await(); 128 } catch (Exception e) { 129 e.printStackTrace(); 130 } 131 } 132 }; 133 service.execute(runnable); 134 } 135 service.shutdown(); 136 } 137 138 } 139 140 /* 141 * 运行结果: 142 线程 pool-1-thread-2 即将到达集合地点1,当前已有 1已经到达;正在等候! 143 线程 pool-1-thread-3 即将到达集合地点1,当前已有 2已经到达;正在等候! 144 线程 pool-1-thread-1 即将到达集合地点1,当前已有 3已经到达;都到齐了,继续走啊! 145 线程 pool-1-thread-2 即将到达集合地点2,当前已有 1已经到达;正在等候! 146 线程 pool-1-thread-1 即将到达集合地点2,当前已有 2已经到达;正在等候! 147 线程 pool-1-thread-3 即将到达集合地点2,当前已有 3已经到达;都到齐了,继续走啊! 148 线程 pool-1-thread-3 即将到达集合地点3,当前已有 1已经到达;正在等候! 149 线程 pool-1-thread-2 即将到达集合地点3,当前已有 2已经到达;正在等候! 150 线程 pool-1-thread-1 即将到达集合地点3,当前已有 3已经到达;都到齐了,继续走啊! 151 */ 152 153 4. CountDownLacth工具类的使用案例 154 package com.java5.thread.newSkill; 155 156 import java.util.concurrent.CountDownLatch; 157 import java.util.concurrent.ExecutorService; 158 import java.util.concurrent.Executors; 159 160 /** 161 * CountDownLacth工具类的使用案例 162 * 犹如倒计时计数器 163 * latch:门闩,闩门 164 * 应用场景:运动员比赛;裁判计时!一款比赛小游戏 165 * 下面例子:三个线程好比三个运动员,主线程好比一个裁判 166 */ 167 public class CountDownLatchTest { 168 169 public static void main(String[] args) { 170 171 ExecutorService service = Executors.newCachedThreadPool(); 172 173 //设置一个数量为1的计时器 174 final CountDownLatch cdOrder = new CountDownLatch(1); 175 //设置一个数量为3的计时器 176 final CountDownLatch cdAnswer = new CountDownLatch(3); 177 for(int i=0;i<3;i++){ 178 Runnable runnable= new Runnable() { 179 180 @Override 181 public void run() { 182 try { 183 System.out.println("线程 "+ Thread.currentThread().getName()+"正准备接受命令!"); 184 185 /*开启三个线程,都在这里等待; 186 * 如何开始下一步呢!?就是再开启一个主线程来用countDown()方法; 187 * 来进行减数,减到0就可以进行下一步程序 188 */ 189 cdOrder.await(); 190 191 System.out.println("线程 "+ Thread.currentThread().getName()+"已接受命令!"); 192 Thread.sleep((long)Math.random()*10000); 193 System.out.println("线程 "+ Thread.currentThread().getName()+"回应命令处理结果!"); 194 195 //countDown();方法就是将计数器身上的计数减1 196 cdAnswer.countDown(); 197 198 } catch (Exception e) { 199 e.printStackTrace(); 200 } 201 } 202 }; 203 service.execute(runnable); 204 } 205 try { 206 Thread.sleep((long)Math.random()*10000); 207 System.out.println("线程 "+ Thread.currentThread().getName()+"即将发布命令!"); 208 209 cdOrder.countDown(); 210 211 System.out.println("线程 "+ Thread.currentThread().getName()+"已发送命令,正在等待结果!"); 212 213 cdOrder.await(); 214 215 System.out.println("线程 "+ Thread.currentThread().getName()+"已收到所有响应结果!"); 216 217 cdAnswer.countDown(); 218 219 } catch (Exception e) { 220 e.printStackTrace(); 221 } 222 service.shutdown(); 223 } 224 225 } 226 5. Exchanger工具类的使用案例 227 package com.java5.thread.newSkill; 228 229 import java.util.concurrent.Exchanger; 230 import java.util.concurrent.ExecutorService; 231 import java.util.concurrent.Executors; 232 233 /** 234 * Exchanger工具类的使用案例 235 * 应用场景:交易性应用或游戏 236 * 两个人碰在一起,交换彼此的数据 237 */ 238 public class ExchangerTest { 239 240 public static void main(String[] args) { 241 242 ExecutorService service = Executors.newCachedThreadPool(); 243 final Exchanger exchanger = new Exchanger(); 244 service.execute(new Runnable() { 245 246 @Override 247 public void run() { 248 try{ 249 250 String data1 = "杨凯"; 251 System.out.println("线程 "+Thread.currentThread().getName()+" 正在把数据: "+data1+" 换出去!"); 252 253 Thread.sleep((long)Math.random()*10000); 254 255 String data2 = (String) exchanger.exchange(data1); 256 System.out.println("线程 "+Thread.currentThread().getName()+" 换回的数据为:"+data2); 257 }catch(Exception e){ 258 259 } 260 } 261 }); 262 service.execute(new Runnable() { 263 264 @Override 265 public void run() { 266 try{ 267 268 String data1 = "杨旋"; 269 System.out.println("线程 "+Thread.currentThread().getName()+" 正在把数据: "+data1+" 换出去!"); 270 271 Thread.sleep((long)Math.random()*10000); 272 273 String data2 = (String) exchanger.exchange(data1); 274 System.out.println("线程 "+Thread.currentThread().getName()+" 换回的数据为:"+data2); 275 }catch(Exception e){ 276 277 } 278 } 279 }); 280 281 } 282 283 }