标签:condition 返回值 throw cal 中断 exce 不同 ted 信号量
1. synchronized和lock的区别:
共同注意点:
睡眠建议使用TimeUnit类,不建议使用sleep;
在多线程下用 if () 判断条件是不安全的, 应该用while () 进行判断。
private int num = 0; public synchronized void add() throws Exception { // 判断 while (num != 0) { // 若此处用if()进行判断,在多线程下结果错误 this.wait(); } // 进行业务编码 num++; System.out.println(Thread.currentThread().getName()+"\t"+num); // 通知 this.notifyAll(); }
使用synchronized 关键字,notify() (Object类中方法) 不能精准唤醒线程,唤醒线程由Java虚拟机决定。
使用lock锁,可实现Condition接口,signal() 方法可精准唤醒线程。
private int num = 1; Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); public void print5() { lock.lock(); try { while (num != 1) { condition1.await(); } for (int i = 1; i <= 5; i++) { System.out.print(Thread.currentThread().getName() + "\t" + i + "->"); } System.out.println(); num = 2; condition2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void print10() { lock.lock(); try { while (num != 2) { condition2.await(); } for (int i = 1; i <= 10; i++) { System.out.print(Thread.currentThread().getName() + "\t" + i + "->"); } System.out.println(); num = 3; condition3.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void print15() { lock.lock(); try { while (num != 3) { condition3.await(); } for (int i = 1; i <= 15; i++) { System.out.print(Thread.currentThread().getName() + "\t" + i + "->"); } System.out.println(); num = 1; condition1.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } }
2. 多线程下使用的辅助类
倒计时计数达到参数数量,即释放阻塞,执行后续操作
CountDownLatch countDownLatch = new CountDownLatch(8); // 参数:线程数 for (int i = 0; i < 6; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName()+"_start"); countDownLatch.countDown(); // 每执行一个线程,参数-1 }).start(); } countDownLatch.await(); // 当达到参数指定的线程数,释放阻塞 System.out.println(Thread.currentThread().getName()+"_end");
举例:集龙珠,每集齐一颗龙珠(线程),计数+1 ,当龙珠数量达到7 ,即可召唤神龙 (只要执行的线程足够,即可循环召唤神龙)
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, new Runnable() { // 参数1:线程数量 参数2:待执行的操作 @Override public void run() { System.out.println("hello..."); } }); for (int i = 0; i < 7; i++) { new Thread(()-> { System.out.println(Thread.currentThread().getName()+"_start"); try { cyclicBarrier.await(); // 循环计数并等待 } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); }
举例:抢车位,参数为车位数,同时获得许可证的车(线程)一共3个,当车开走,后面的才可获得许可证进入
Semaphore semaphore = new Semaphore(3); 参数:线程数量 for (int i = 0; i < 6; i++) { new Thread(() -> { try { semaphore.acquire(); // 获取许可证 System.out.println(Thread.currentThread().getName()+"到了"); TimeUnit.SECONDS.sleep(3); // 睡眠建议用TimeUnit类,不建议使用sleep System.out.println(Thread.currentThread().getName()+"走了"); TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); // 释放许可证 } }).start(); }
3. callable 和 runnable 的区别:
通过源码发现 FutrueTask<> 类可使两者产生联系
标签:condition 返回值 throw cal 中断 exce 不同 ted 信号量
原文地址:https://www.cnblogs.com/ShallowPen/p/12398254.html