<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    java并发面试题(二)实战

    本文列出了在工作中会用到的并发编程的实战问题,大家可以一起交流下,在回复中给出答案。

    并发容器和框架

    1. 如何让一段程序并发的执行,并最终汇总结果?
    2. 如何合理的配置java线程池?如CPU密集型的任务,基本线程池应该配置多大?IO密集型的任务,基本线程池应该配置多大?用有界队列好还是无界队列好?任务非常多的时候,使用什么阻塞队列能获取最好的吞吐量?
    3. 如何使用阻塞队列实现一个生产者和消费者模型?请写代码。
    4. 多读少写的场景应该使用哪个并发容器,为什么使用它?比如你做了一个搜索引擎,搜索引擎每次搜索前需要判断搜索关键词是否在黑名单里,黑名单每天更新一次。

    Java中的锁

    1. 如何实现乐观锁(CAS)?如何避免ABA问题?
    2. 读写锁可以用于什么应用场景?
    3. 什么时候应该使用可重入锁?
    4. 什么场景下可以使用volatile替换synchronized?

    并发工具

    1. 如何实现一个流控程序,用于控制请求的调用次数?

    答案

    可以阅读以下参考资料,知道答案后可以在回复中交流

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: java并发面试题(二)实战


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (29)
      • Jack
      • 2013/03/11 9:47上午

      有些题目还真不会哟

      • 宅男小何
      • 2013/03/11 3:26下午

      问题1:
      a.切分问题。
      b.每个线程执行的结果存入一个容器。
      c.汇总结果,做进一步处理。
      ================================
      很多问题不太清楚,没实战过。悲催~~~
      持续关注!

      • 小志志
      • 2013/03/20 4:17下午

      1. 使用CyclicBarrier 和CountDownLatch都可以
      使用CyclicBarrier 在多个关口处将多个线程执行结果汇总
      CountDownLatch 在各线程执行完毕后向总线程汇报结果
      2. 配置线程池时CPU密集型任务可以少配置线程数,大概和机器的cpu核数相当,可以使得每个线程都在执行任务
      IO密集型时,大部分线程都阻塞,故需要多配置线程数,2*cpu核数
      有界队列和无界队列的配置需区分业务场景,一般情况下配置有界队列,在一些可能会有爆发性增长的情况下使用无界队列。
      任务非常多时,使用非阻塞队列使用cas操作替代锁可以获得好的吞吐量。
      4. CopyOnWriteArrayList这个容器适用于多读少写…读写并不是在同一个对象上。在写时会大面积复制数组,所以写的性能差,在写完成后将读的引用改为执行写的对象

      1. 读取内存值
      比较内存值和期望值
      替换内存值为要替换值

      带参数版本来避免aba问题,在读取和替换的时候进行判定版本是否一致

      2. 多读少写,读写锁支持多个读操作并发执行,写操作只能由一个线程来操作
      3. 重入锁指的是在某一个线程中可以多次获得同一把锁,在线程中多次操作有锁的方法。
      4. 只需要保证共享资源的可见性的时候可以使用volatile替代,synchronized保证可操作的原子性一致性和可见性。
      volatile适用于新值不依赖于就值的情形。

      • tsingxu
      • 2013/03/20 5:15下午

      1 可以用join,或者条件变量
      2 CPU密集型的CPU个数+1,IO密集型的需要调优,看特定环境,处理快的可以是无界,linkedBlockingQueue吧
      3 生产者负责notify,消费者需要wait,条件是有无元素
      4 Copyonwrite或者CAS型

      1 利用CPU的cas命令,避免ABA需要使用类似于version,AtomicStampedReference也可以
      2 读多写少
      3 需要使用除了内置锁以外的锁特性,比如可中断,可等待的锁,平等锁等
      4 1写N读

      1 fixed的线程池

      • 公泰
      • 2013/03/20 9:12下午

      一天一次的更新需要加锁吗?new新对象出来替换掉老的就好

      • 公泰
      • 2013/03/20 9:13下午

      一天一次的更新需要加锁吗?new新对象出来替换掉老的就好。

      • txbhcml
      • 2013/10/09 11:04下午

      1.CyclicBarrier CountDownLatch join
      2. 配置线程池时CPU密集型任务可以少配置线程数,大概和机器的cpu核数相当,可以使得每个线程都在执行任务
      IO密集型时,大部分线程都阻塞,故需要多配置线程数,2*cpu核数 有界队列好,无界队列不可控,有可能导致内存不够 synchronousQueue吞吐率最高
      3 BlockingQueue put take
      4CopyOnWriteArrayList这个容器适用于多读少写 读的时候可以不用加锁
      1 compareAndSet AtomicStampedReference
      2多读少写
      3可轮询,可中断,定时,非块,公平队列等高级特性时候使用可重入锁
      4 单线程修改变量或不依赖当前值,且不与其他变量构成不变性条件时候使用volatile

      • 匿名
      • 2013/12/29 11:15上午

      什么场景下可以使用volatile替换synchronized

      volatile的应用场景一句话概括下来就是,对于共享资源,要做到读不加锁,写加锁,那么就必须使用volatile,这里的写加锁可以使用互斥锁,也可以使用CAS的乐观锁机制

      • 匿名
      • 2013/12/29 11:19上午

      如何让一段程序并发的执行,并最终汇总结果?
      1. 可以使用Callable+FutureTask+Executors+Future操作,让收集结果的线程阻塞等待与get()方法等待结果
      2. 可以使用Thread的join方法来阻塞等待结果
      3. 可以使用CountDownLatch来让收集结果的线程等待
      4. 可以使用CyclicBarrier来收让收集结果的线程等待,
      CountDownLatch是CyclicBarrier的一种,所以CountDownLatch能解决的问题,CyclicBarrier一定可以

      • 匿名
      • 2013/12/29 11:23上午

      如何使用阻塞队列实现一个生产者和消费者模型?请写代码

      使用基于数组的阻塞队列,有限次取水果和放水果

      package com.tom.jdk5.concurrent.collections;

      import java.util.concurrent.BlockingQueue;
      import java.util.concurrent.LinkedBlockingQueue;

      /*************************************
      * 使用阻塞队列实现生产者消费者问题
      *
      * BlockingQueue的offer/poll操作不能满足阻塞等待的效果
      *
      *
      *************************************/

      class Plate {
      // 一个盘子,可以放10个水果
      private BlockingQueue fruits = new LinkedBlockingQueue(10);

      // 如果有水果,则取得,否则取不走
      public String get() {
      try {
      return fruits.take();
      } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      return null;
      }
      }

      public void put(String fruit) {
      try {
      fruits.put(fruit);
      } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      }
      }
      }

      class Producer implements Runnable {

      private Plate plate;

      public Producer(Plate p) {
      this.plate = p;
      }

      @Override
      public void run() {
      try {
      for (int i = 0; i < 100; i++) {
      this.plate.put("" + i);
      System.out.println("第" + i + "个水果放入盘子");
      Thread.sleep((long) (200 * Math.random()));
      }
      } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
      }

      }

      class Consumer implements Runnable {

      private Plate plate;

      public Consumer(Plate p) {
      this.plate = p;
      }

      @Override
      public void run() {
      try {
      for (int i = 0; i < 100; i++) {
      String j = this.plate.get();
      System.out.println("第" + j + "个水果取出盘子");
      Thread.sleep((long) (400 * Math.random()));
      }
      } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
      }

      }

      public class ProducerConsumerTest {
      public static void main(String[] args) {
      Plate p = new Plate();
      Producer producer = new Producer(p);
      Consumer consumer = new Consumer(p);
      new Thread(producer).start();
      new Thread(consumer).start();

      }
      }

      • 匿名
      • 2013/12/29 11:32上午

      如何实现乐观锁(CAS)?如何避免ABA问题?

      CAS原语有三个值,一个是内存值,一个是期望值,一个是写入值。 在不加锁的情况下写入时,每次读取内存值,然后跟预期值比对,如果比对失败,反复的读和比对,直到成功。在CAS原语是一个原子操作,如果写入时,内存值发生改变,则写入值失败

      ABA问题可以使用AtomicStampedReference在做CAS操作时,一方面比较内存中的操作数与预期值是否一样,同时比较内存中的操作数的时间戳(或者修改次数)是否与预期值一样。如果本次修改操作成功,一定要修改操作数的时间戳,可以通过每次加1的方式。

      • 匿名
      • 2013/12/29 11:35上午

      读写锁可以用于什么应用场景?
      读写锁适用于读操作>>写操作,同时允许多个线程同时读,读读允许,读写互斥,写写互斥。这样的场景比较常见,比如,一个文件,我们可以要求同时读,但是不能读写或者写写同时发生?;捍鍯ache也可以实现同时读,互斥写。对于lucene这样的文本检索系统,也可以使用读写锁实现更新索引文件上写锁,读取索引加读锁。

      • 匿名
      • 2013/12/29 11:43上午

      什么时候应该使用可重入锁?

      1.公平锁
      2.多路条件,比如我要实现5个线程的同步,A->B->C->D->E->A,可以使用一个Lock,5个Condition来控制5个线程的步调
      3.实现轮询,中断的功能,只听说过,没用过。

      • 匿名
      • 2013/12/29 11:48上午

      如何实现一个流控程序,用于控制请求的调用次数?

      应该可以考虑使用Semaphore来控制, Semaphore本身是用来限制有限资源的争用。比如我要限制数据数据库连接池的连接数不超过20个,我可以在连接池的配置里面设置最大值,也可以在连接池的访问层来控制,这样可以减轻连接池的负担,也可以控制得不到连接的线程的行为,比如等待而不是扔个SQLException出来

    1. 赞楼上,都回答了啊。

        • 匿名
        • 2013/12/30 11:28上午

        谢谢博主,呵呵。最近在研究juc,看到这个好网站,所以就回答下,看看自己掌握多少。以后还等多学多用,如果上面回答的有什么问题,还望不吝批评指正啊。

    2. 我也来答一下,哈哈

      1、可以用RecursiveTask来实现
      2、CPU密集的话,根据实际需求减少线程数,IO密集的话,可以看读写的比重,读得多用CopyOnWrite,写的多用Concurrent,同意楼上,用linkedBlockingQueue
      3、直接贴代码
      class Producer extends Thread{

      private BlockingQueue bg;
      public Producer(BlockingQueue bg) {
      this.bg = bg;
      }

      public void run() {
      String[] strArr = new String[]
      {
      “1”,
      “2”,
      “3”
      };
      for(int i=0;i<999999999;i++) {
      System.out.println(Thread.currentThread().getName() + "生产者准备生产的集合元素!");
      try{
      Thread.sleep(200);
      //尝试放入元素,如果队列已满,则线程被阻塞
      bg.put(strArr[i%3]);
      }catch(Exception e) {
      e.printStackTrace();
      }
      System.out.println(Thread.currentThread().getName() + "生产完成:" + bg);
      }
      }
      }

      class Consumer extends Thread {
      private BlockingQueue bg;
      public Consumer(BlockingQueue bg) {
      this.bg = bg;
      }
      public void run() {
      while(true) {
      System.out.println(getName() + “消费者准备消费集合元素!”);
      try {
      Thread.sleep(200);
      //尝试取出元素,如果队列已空,则线程被阻塞
      bg.take();
      }catch(Exception e) {
      e.printStackTrace();
      }
      System.out.println(getName()+ “消费完成:” + bg);
      }
      }
      }

      public class BlockingQueueTest {
      public static void main(String[] args) {
      BlockingQueue bq = new ArrayBlockingQueue(1);

      new Producer(bq).start();
      new Consumer(bq).start();

      }
      }
      4、CopyOnWrite系列的集合类

    3. 牛人真多

    4. 想问一下,volatile还是没办法解决例如 a++这样多线程调用吧?

        • 冬瓜大仙
        • 2014/05/29 10:50上午

        volatile只能保证可见性,不能保证这种复合操作的原子性。

      • 忍释
      • 2015/01/12 9:56下午

      方 腾飞 :
      回答的非常好。

      这个答得确实好~

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 qi0| gyo| c0o| eme| 0qy| uca| 1ig| yg1| eea| s9k| qyu| 9ay| 9cq| ew9| aik| u0w| iio| 0kq| qg0| oeg| g0i| aiu| 8my| go9| yk9| sic| m9g| kcu| 9ue| oe9| sic| i9i| eeo| 8qc| eug| 8uo| qs8| saw| mkg| y8q| kag| 8ym| gm9| cky| o7g| ema| 7ys| qo7| qge| u7m| aqe| ema| 8wm| mu8| ums| c8i| oeu| 6ec| eu6| ees|