V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
mmdsun
V2EX  ›  问与答

请教一 Java 多线程设计的问题

  •  
  •   mmdsun · Mar 18, 2019 via Android · 2245 views
    This topic created in 2599 days ago, the information mentioned may be changed or developed.

    多个线程,同时分页查询数据库每次 1000 条,然后 java 程序过滤这一千条数据,将满足条件的数据被 add 一个新集合里面,这个集合每 100 条输出一次 Excel。

    我隐约记得 java 的某些集合的 add 操作不是线程安全的,有些并发容器 size 判断会不准确。还得满足条件 100 条输出一次(此时 add 操作应该会暂停),不足 100 条等待下一次 1000 条查询。

    请问这种需求应该如何设计多线程? java 有否这种生产者模式的 api,类库等。

    12 replies    2019-03-18 17:39:09 +08:00
    sundae91
        1
    sundae91  
       Mar 18, 2019
    CopyOnWriteArrayList?
    kiddult
        2
    kiddult  
       Mar 18, 2019
    生产者+消费者,消费者单线程执行
    momocraft
        3
    momocraft  
       Mar 18, 2019
    java.util.concurrent 有线程安全的容器
    rockyou12
        4
    rockyou12  
       Mar 18, 2019   ❤️ 1
    你查数据库量级多少,查询条件复杂不?如果不复杂量,量级就万来条你单线程不分页可能还快些。

    如果你 Java 里过滤条件比较耗时,直接用 parallelStream().filter().sequential() 这样结果也是保证顺序的
    peyppicp
        5
    peyppicp  
       Mar 18, 2019   ❤️ 1
    首先 new 一个 Object 作为互斥量,创建一个 LinkedList 或者什么,两个方法一个写入数据,一个读取数据,针对这个 Object 上锁。取数据得时候 for 循环到 100 条之后退出循环即可

    对于数据库查询 1000 条数据,然后过滤的需求,使用线程池搞定,向线程池提交 Future,然后在 Future 里对数据进行处理,然后调用写入数据的方法写入数据

    如果想准确得知 list 的 size,就直接包装一层,先拿锁,再调用 list.size 方法。就我看来读取数据库时间应该远超锁切换时间,应该是值得的
    不知道我讲清楚了没有。。
    peyppicp
        6
    peyppicp  
       Mar 18, 2019
    其实性能不重要的场景 用不用并发容器都无所谓,自己用 sync 关键字包一层就完事了
    mmdsun
        7
    mmdsun  
    OP
       Mar 18, 2019 via Android
    @sundae91 @kiddult @momocraft @rockyou12 @peyppicp

    谢谢大家,目前打算使用加锁的方案。数据库查询还是比较耗时的操作。

    看了几个 java 并发容器的 api 感觉场景不适合,比如 CopyOnWriteArrayList 用在读多写少的场景会更好。另外发现 java 的一些阻塞队列 api 应该可以做到,但由于不太熟悉 api 害怕会有什么坑。暂时打算加锁解决。
    Lattez
        8
    Lattez  
       Mar 18, 2019
    看了一眼之前写的,也是分页 1000 查的数据写 Excel,用的是 CopyOnWriteArrayList,当然这玩意本身底层实现就是 add 的时候上锁拷贝的
    Weixiao0725
        9
    Weixiao0725  
       Mar 18, 2019
    这个用条件变量可以实现吧
    JohnZorn
        10
    JohnZorn  
       Mar 18, 2019 via Android
    都说生产者消费者了,阻塞队列不行吗?有个什么 blockinglinkedqueue?
    JohnZorn
        11
    JohnZorn  
       Mar 18, 2019 via Android
    #10 LinkedBlockingQueue
    mccreefei
        12
    mccreefei  
       Mar 18, 2019
    每个线程处理 1000 条,每过滤出 100 条有效数据封装一下塞到阻塞队列里,多余的数据加锁暂时存放到 list 中,消费者线程从阻塞队列里 100 条、100 条地拿数据写 excel,利用 countDownLatch,最后一个生产者线程处理那个 list ( list 中每 100 条塞阻塞队列)。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4869 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 216ms · UTC 09:48 · PVG 17:48 · LAX 02:48 · JFK 05:48
    ♥ Do have faith in what you're doing.