当前位置: 首页 > news >正文

陕西省住房和城乡建设厅门户网站万户网络做网站

陕西省住房和城乡建设厅门户网站,万户网络做网站,苏州园区网站建设公司,广告设计专业需要学什么Keeper导读大家在换工作面试中#xff0c;除了一些常规算法题#xff0c;还会遇到各种需要手写的题目#xff0c;所以打算总结出来#xff0c;给大家个参考。全文 2929 字#xff0c;剩下的是代码#xff0c;P6 及以下阅读只需要 8 分钟#xff0c;高 P 请直接关闭第一篇… Keeper导读大家在换工作面试中除了一些常规算法题还会遇到各种需要手写的题目所以打算总结出来给大家个参考。全文 2929 字剩下的是代码P6 及以下阅读只需要 8 分钟高 P 请直接关闭第一篇打算总结下阿里最喜欢问的多个线程顺序打印问题我遇到的是机试直接写出运行。同类型的题目有很多比如三个线程分别打印 ABC要求这三个线程一起运行打印 n 次输出形如“ABCABCABC....”的字符串两个线程交替打印 0~100 的奇偶数通过 N 个线程顺序循环打印从 0 至 100多线程按顺序调用A-B-CAA 打印 5 次BB 打印10 次CC 打印 15 次重复 10 次用两个线程一个输出字母一个输出数字交替输出 1A2B3C4D...26Z其实这类题目考察的都是线程间的通信问题基于这类题目做一个整理方便日后手撕面试官文明的打工人手撕面试题。1.使用 Lock我们以第一题为例三个线程分别打印 ABC要求这三个线程一起运行打印 n 次输出形如“ABCABCABC....”的字符串。思路使用一个取模的判断逻辑 C%M N题为 3 个线程所以可以按取模结果编号0、1、2他们与 3 取模结果仍为本身则执行打印逻辑。public class PrintABCUsingLock {private int times; // 控制打印次数private int state;   // 当前状态值保证三个线程之间交替打印private Lock lock  new ReentrantLock();public PrintABCUsingLock(int times) {this.times  times;}private void printLetter(String name, int targetNum) {for (int i  0; i  times; ) {lock.lock();if (state % 3  targetNum) {state;i;System.out.print(name);}lock.unlock();}}public static void main(String[] args) {PrintABCUsingLock loopThread  new PrintABCUsingLock(1);new Thread(() - {loopThread.printLetter(B, 1);}, B).start();new Thread(() - {loopThread.printLetter(A, 0);}, A).start();new Thread(() - {loopThread.printLetter(C, 2);}, C).start();} } main 方法启动后3 个线程会抢锁但是 state 的初始值为 0所以第一次执行 if  语句的内容只能是 线程 A然后还在 for 循环之内此时 state 1只有 线程 B 才满足 1% 3 1所以第二个执行的是 B同理只有 线程 C 才满足 2% 3 2所以第三个执行的是 C执行完 ABC 之后才去执行第二次 for 循环所以要把 i 写在 for 循环里边不能写成 for (int i 0; i times;i)  这样。2.使用 wait/notify其实遇到这类型题目好多同学可能会先想到的就是 join()或者 wati/notify 这样的思路。算是比较传统且万能的解决方案。也有些面试官会要求不能使用这种方式。思路还是以第一题为例我们用对象监视器来实现通过 wait 和 notify() 方法来实现等待、通知的逻辑A 执行后唤醒 BB 执行后唤醒 CC 执行后再唤醒 A这样循环的等待、唤醒来达到目的。public class PrintABCUsingWaitNotify {private int state;private int times;private static final Object LOCK  new Object();public PrintABCUsingWaitNotify(int times) {this.times  times;}public static void main(String[] args) {PrintABCUsingWaitNotify printABC  new PrintABCUsingWaitNotify(10);new Thread(() - {printABC.printLetter(A, 0);}, A).start();new Thread(() - {printABC.printLetter(B, 1);}, B).start();new Thread(() - {printABC.printLetter(C, 2);}, C).start();}private void printLetter(String name, int targetState) {for (int i  0; i  times; i) {synchronized (LOCK) {while (state % 3 ! targetState) {try {LOCK.wait();} catch (InterruptedException e) {e.printStackTrace();}}state;System.out.print(name);LOCK.notifyAll();}}} } 同样的思路来解决下第 2 题两个线程交替打印奇数和偶数使用对象监视器实现两个线程 A、B 竞争同一把锁只要其中一个线程获取锁成功就打印 i并通知另一线程从等待集合中释放然后自身线程加入等待集合并释放锁即可。图throwable-blogpublic class OddEvenPrinter {private Object monitor  new Object();private final int limit;private volatile int count;OddEvenPrinter(int initCount, int times) {this.count  initCount;this.limit  times;}public static void main(String[] args) {OddEvenPrinter printer  new OddEvenPrinter(0, 10);new Thread(printer::print, odd).start();new Thread(printer::print, even).start();}private void print() {synchronized (monitor) {while (count  limit) {try {System.out.println(String.format(线程[%s]打印数字:%d, Thread.currentThread().getName(), count));monitor.notifyAll();monitor.wait();} catch (InterruptedException e) {e.printStackTrace();}}//防止有子线程被阻塞未被唤醒导致主线程不退出monitor.notifyAll();}} } 同样的思路来解决下第 5 题用两个线程一个输出字母一个输出数字交替输出 1A2B3C4D...26Zpublic class NumAndLetterPrinter {private static char c  A;private static int i  0;static final Object lock  new Object();public static void main(String[] args) {new Thread(() - printer(), numThread).start();new Thread(() - printer(), letterThread).start();}private static void printer() {synchronized (lock) {for (int i  0; i  26; i) {if (Thread.currentThread().getName()  numThread) {//打印数字1-26System.out.print((i  1));// 唤醒其他在等待的线程lock.notifyAll();try {// 让当前线程释放锁资源进入wait状态lock.wait();} catch (InterruptedException e) {e.printStackTrace();}} else if (Thread.currentThread().getName()  letterThread) {// 打印字母A-ZSystem.out.print((char) (A  i));// 唤醒其他在等待的线程lock.notifyAll();try {// 让当前线程释放锁资源进入wait状态lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}}lock.notifyAll();}} } 3.使用 Lock/Condition还是以第一题为例使用 Condition 来实现其实和 wait/notify 的思路一样。Condition 中的 await() 方法相当于 Object 的 wait() 方法Condition 中的 signal() 方法相当于Object 的 notify() 方法Condition 中的 signalAll() 相当于 Object 的 notifyAll() 方法。不同的是Object 中的 wait(),notify(),notifyAll()方法是和同步锁(synchronized关键字)捆绑使用的而 Condition 是需要与互斥锁/共享锁捆绑使用的。public class PrintABCUsingLockCondition {private int times;private int state;private static Lock lock  new ReentrantLock();private static Condition c1  lock.newCondition();private static Condition c2  lock.newCondition();private static Condition c3  lock.newCondition();public PrintABCUsingLockCondition(int times) {this.times  times;}public static void main(String[] args) {PrintABCUsingLockCondition print  new PrintABCUsingLockCondition(10);new Thread(() - {print.printLetter(A, 0, c1, c2);}, A).start();new Thread(() - {print.printLetter(B, 1, c2, c3);}, B).start();new Thread(() - {print.printLetter(C, 2, c3, c1);}, C).start();}private void printLetter(String name, int targetState, Condition current, Condition next) {for (int i  0; i  times; ) {lock.lock();try {while (state % 3 ! targetState) {current.await();}state;i;System.out.print(name);next.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}} } 使用 Lock 锁的多个 Condition 可以实现精准唤醒所以碰到那种多个线程交替打印不同次数的题就比较容易想到比如解决第四题多线程按顺序调用A-B-CAA 打印 5 次BB 打印10 次CC 打印 15 次重复 10 次代码就不贴了思路相同。以上几种方式其实都会存在一个锁的抢夺过程如果抢锁的的线程数量足够大就会出现很多线程抢到了锁但不该自己执行然后就又解锁或 wait() 这种操作这样其实是有些浪费资源的。4.使用 Semaphore在信号量上我们定义两种操作信号量主要用于两个目的一个是用于多个共享资源的互斥使用另一个用于并发线程数的控制。acquire获取 当一个线程调用 acquire 操作时它要么通过成功获取信号量信号量减1要么一直等下去直到有线程释放信号量或超时。release释放实际上会将信号量的值加1然后唤醒等待的线程。先看下如何解决第一题三个线程循环打印 ABCpublic class PrintABCUsingSemaphore {private int times;private static Semaphore semaphoreA  new Semaphore(1); // 只有A 初始信号量为1,第一次获取到的只能是Aprivate static Semaphore semaphoreB  new Semaphore(0);private static Semaphore semaphoreC  new Semaphore(0);public PrintABCUsingSemaphore(int times) {this.times  times;}public static void main(String[] args) {PrintABCUsingSemaphore printer  new PrintABCUsingSemaphore(1);new Thread(() - {printer.print(A, semaphoreA, semaphoreB);}, A).start();new Thread(() - {printer.print(B, semaphoreB, semaphoreC);}, B).start();new Thread(() - {printer.print(C, semaphoreC, semaphoreA);}, C).start();}private void print(String name, Semaphore current, Semaphore next) {for (int i  0; i  times; i) {try {System.out.println(111  Thread.currentThread().getName());current.acquire();  // A获取信号执行,A信号量减1,当A为0时将无法继续获得该信号量System.out.print(name);next.release();    // B释放信号B信号量加1初始为0此时可以获取B信号量System.out.println(222  Thread.currentThread().getName());} catch (InterruptedException e) {e.printStackTrace();}}} } 如果题目中是多个线程循环打印的话一般使用信号量解决是效率较高的方案上一个线程持有下一个线程的信号量通过一个信号量数组将全部关联起来这种方式不会存在浪费资源的情况。接着用信号量的方式解决下第三题通过 N 个线程顺序循环打印从 0 至 100public class LoopPrinter {private final static int THREAD_COUNT  3;static int result  0;static int maxNum  10;public static void main(String[] args) throws InterruptedException {final Semaphore[] semaphores  new Semaphore[THREAD_COUNT];for (int i  0; i  THREAD_COUNT; i) {//非公平信号量每个信号量初始计数都为1semaphores[i]  new Semaphore(1);if (i ! THREAD_COUNT - 1) {System.out.println(isemaphores[i].getQueueLength());//获取一个许可前线程将一直阻塞, for 循环之后只有 syncObjects[2] 没有被阻塞semaphores[i].acquire();}}for (int i  0; i  THREAD_COUNT; i) {// 初次执行上一个信号量是 syncObjects[2]final Semaphore lastSemphore  i  0 ? semaphores[THREAD_COUNT - 1] : semaphores[i - 1];final Semaphore currentSemphore  semaphores[i];final int index  i;new Thread(() - {try {while (true) {// 初次执行让第一个 for 循环没有阻塞的 syncObjects[2] 先获得令牌阻塞了lastSemphore.acquire();System.out.println(thread  index  :   result);if (result  maxNum) {System.exit(0);}// 释放当前的信号量syncObjects[0] 信号量此时为 1下次 for 循环中上一个信号量即为syncObjects[0]currentSemphore.release();}} catch (Exception e) {e.printStackTrace();}}).start();}} } 5.使用 LockSupportLockSupport 是 JDK 底层的基于 sun.misc.Unsafe 来实现的类用来创建锁和其他同步工具类的基本线程阻塞原语。它的静态方法unpark()和park()可以分别实现阻塞当前线程和唤醒指定线程的效果所以用它解决这样的问题会更容易一些。在 AQS 中就是通过调用 LockSupport.park( )和 LockSupport.unpark() 来实现线程的阻塞和唤醒的。public class PrintABCUsingLockSupport {private static Thread threadA, threadB, threadC;public static void main(String[] args) {threadA  new Thread(() - {for (int i  0; i  10; i) {// 打印当前线程名称System.out.print(Thread.currentThread().getName());// 唤醒下一个线程LockSupport.unpark(threadB);// 当前线程阻塞LockSupport.park();}}, A);threadB  new Thread(() - {for (int i  0; i  10; i) {// 先阻塞等待被唤醒LockSupport.park();System.out.print(Thread.currentThread().getName());// 唤醒下一个线程LockSupport.unpark(threadC);}}, B);threadC  new Thread(() - {for (int i  0; i  10; i) {// 先阻塞等待被唤醒LockSupport.park();System.out.print(Thread.currentThread().getName());// 唤醒下一个线程LockSupport.unpark(threadA);}}, C);threadA.start();threadB.start();threadC.start();} } 理解了思路解决其他问题就容易太多了。比如我们再解决下第五题用两个线程一个输出字母一个输出数字交替输出 1A2B3C4D...26Zpublic class NumAndLetterPrinter {private static Thread numThread, letterThread;public static void main(String[] args) {letterThread  new Thread(() - {for (int i  0; i  26; i) {System.out.print((char) (A  i));LockSupport.unpark(numThread);LockSupport.park();}}, letterThread);numThread  new Thread(() - {for (int i  1; i  26; i) {System.out.print(i);LockSupport.park();LockSupport.unpark(letterThread);}}, numThread);numThread.start();letterThread.start();} } 写在最后好了以上就是常用的五种实现方案多练习几次手撕没问题。当然这类问题解决方式不止是我列出的这些还会有 join、CountDownLatch、也有放在队列里解决的思路有很多面试官想考察的其实只是对多线程的编程功底其实自己练习的时候是个很好的巩固理解 JUC 的过程。 往期推荐 多图带你彻底理解Java中的21种锁2020-09-24 Java中的5大队列你知道几个2020-10-24 队列实现栈的3种方法全都击败了100%的用户2020-11-02 关注我每天陪你进步一点点
http://www.zqtcl.cn/news/993721/

相关文章:

  • 横岗网站建设无锡网站seo外包
  • 房管局 网站做房查学做网站推广要多久时间
  • 电脑网站开发者模式田园综合体建设网站
  • 南宁广告公司网站建设自适应网站建设模板
  • 做北京电梯招标的网站衡阳县专业做淘宝网站
  • 建设网站的语言wordpress主题自定义添加后台设置
  • 制造动漫网站开发目的四川酒店网站建设
  • 中国城市建设研究院深圳分院网站广西圣泰建设工程有限公司网站
  • 网站建设的方法有哪些内容wordpress展示插件
  • 北京手机网站制作公司wordpress 简易教程
  • 手机网站建站公司有哪些搜索引擎收录
  • 仿同程网 连锁酒店 网站模板学校网站建设用哪个系统
  • 教做甜品的网站删除wordpress主题字体载入
  • 做酒店网站所用到的算法wordpress侧栏导航
  • 做漫画的网站有哪些信息门户网站怎么做
  • 九江集团网站建设公司信誉好的广州做网站
  • 福州网站建设服务平台今天发生的重大新闻
  • 招聘信息网搜索引擎优化代理
  • 免费的企业网站cms纯文字logo在线制作
  • 深圳电器公司官网网站建设 网站优化
  • 大连 网站建设昆明建设网站哪家好
  • 网站首页设计及运行效果网站建设与管理任务分工
  • 自己建设论坛网站家用电脑搭建服务器
  • 做网站上海公司企业网站内页
  • 手机网站seo山东网站建设网
  • 溧阳 招网站开发wordpress 占内存
  • 网站seo 工具做网站建设公司排名
  • 丹阳网站建设企业建设网站管理制度
  • 怎样审请网站集成装修全屋定制
  • 好看响应式网站模板下载可以访问的国外网站