exchanger
1.它的使用必须是成对出现的.如果不是成对的话,可能交换错误
2.exchanger 交换的信息是同一个内存地址,而不是copy 会涉及到线程安全的问题
/** * exchange 是成对出现的,如果在有一个线程是A1的话 有可能是交换错误了. *如果超时了.,另一个会不会结束 * @param args */ public static void main(String[] args) { Exchanger<String> exchanger = new Exchanger<>(); new Thread(()->{ try { System.out.println(Thread.currentThread().getName()+" start" ); String exchange = exchanger.exchange("i am come from thread a ",10, TimeUnit.SECONDS); System.out.println(Thread.currentThread().getName()+" 接受 value = "+ exchange); } catch (InterruptedException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); System.out.println("超时..."); } System.out.println(Thread.currentThread().getName()+" end " ); },"A").start(); new Thread(()->{ try { System.out.println(Thread.currentThread().getName()+" start" ); String exchange = exchanger.exchange("i am come from thread a ",10, TimeUnit.SECONDS); System.out.println(Thread.currentThread().getName()+" 接受 value = "+ exchange); } catch (InterruptedException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); System.out.println("超时..."); } System.out.println(Thread.currentThread().getName()+" end " ); },"A1").start(); new Thread(()->{ try { System.out.println(Thread.currentThread().getName()+" start" ); // TimeUnit.SECONDS.sleep(13); String exchange = exchanger.exchange("i am come from thread b "); System.out.println(Thread.currentThread().getName()+" 接受 value = "+ exchange); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" end " ); },"B").start(); }
3.exchanger 是可以一直发生交换的
public static void main(String[] args) { Exchanger<Integer> exchanger = new Exchanger<>(); new Thread(()->{ try { AtomicReference<Integer> atomicReference = new AtomicReference<>(1); while (true){ TimeUnit.SECONDS.sleep(2); Integer exchange = exchanger.exchange(atomicReference.get()); System.out.println(Thread.currentThread().getName()+" 接受 value = "+ exchange); } } catch (InterruptedException e) { e.printStackTrace(); } },"thread-A").start(); new Thread(()->{ try { AtomicReference<Integer> atomicReference = new AtomicReference<>(2); while (true){ TimeUnit.SECONDS.sleep(1); Integer exchange = exchanger.exchange(atomicReference.get()); System.out.println(Thread.currentThread().getName()+" 接受 value = "+ exchange); } } catch (InterruptedException e) { e.printStackTrace(); } },"thread-B").start(); }
semaphore
调用semaphore的话,你可以定义许可证,就是同一个时间.只能这么多线程来访问.
Semaphore semaphore = new Semaphore(2);
public static void main(String[] args) { Semaphore semaphore = new Semaphore(2); for (int i = 0; i <2 ; i++) { new Thread(()->{ System.out.println(Thread.currentThread().getName()+"in"); try { semaphore.acquire(); System.out.println(Thread.currentThread().getName()+" get the semaphore"); TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } semaphore.release(); System.out.println(Thread.currentThread().getName()+"out"); }).start(); } }
如果是一个那么同一时间只能一个.线程
那么他的作用在哪里呢?
我们可以想象,数据库连接池.假设我们有10个连接.但是现在同一个时间来了20个请求.那么就需要等到前面10个连接结束之后就可以连接了.起到了限流作用.
一些策略
1.就是等待阻塞着 .
2.直接中断
3.定时放弃
4.直接获取结果
API的使用
semaphore.availablePermits() 可用的许可证
semaphore.acquireUninterruptibly(); 忽视中断.
semaphore.acquire(2); 一次获取几个许可证
semaphore.drainPermits(); 获取的所有的许可证 释放之后第二个线程才会执行
public static void main(String[] args) throws InterruptedException { Semaphore semaphore = new Semaphore(5); Thread thread = new Thread(() -> { //获取到所有的额 try { semaphore.drainPermits(); System.out.println(Thread.currentThread().getName() + " in"); TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(5); } }); thread.start(); TimeUnit.MILLISECONDS.sleep(50); Thread t2 = new Thread(() -> { try { System.out.println(Thread.currentThread().getName() + " in"); semaphore.acquire(); System.out.println(Thread.currentThread().getName()+" out"); } catch (InterruptedException e) { e.printStackTrace(); }finally { semaphore.release(); } }); t2.start(); }
semaphore.hasQueuedThreads() 是否有线程正在获取信号量
boolean b = semaphore.tryAcquire(); 这个方法是尝试去获取.如果获取不到就算了.
tryAcquier(1,timeUnit.SECONDS) 尝试使用多长时间来获取
public static void main(String[] args) throws InterruptedException { Semaphore semaphore = new Semaphore(1); Thread thread = new Thread(() -> { //获取到所有的额 try { boolean b = semaphore.tryAcquire(); TimeUnit.SECONDS.sleep(2); System.out.println(b); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } }); thread.start(); TimeUnit.MILLISECONDS.sleep(50); Thread t2 = new Thread(() -> { try { boolean b = semaphore.tryAcquire(1,TimeUnit.SECONDS); if(b){ System.out.println(b); System.out.println(Thread.currentThread().getName()+" 可以"); }else{ System.out.println(b); System.out.println(Thread.currentThread().getName()+"不可以"); } } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } }); t2.start(); }