美文网首页
[099]技术-jdk中的多线程相关的基本数据结构

[099]技术-jdk中的多线程相关的基本数据结构

作者: shawnxjf | 来源:发表于2017-12-25 20:48 被阅读0次

    CountdownLatch

    countdownLatch为多个线程整体到达条件时通知await的线程,即时序图如下:


    image.png

    由图中我们知道,执行的.countDown()方法的线程不会阻塞会接着干自己的事情,当thread1,2,3这3个线程都已经执行了countdown的时候就会通知 countdownLatch.await()上等待的线程。 其具体表现是一拨人等另一拨人。

    具体伪代码交互模式为:

    main(){
      CountdownLatch countDownLatch = new CountDownLatch(5);  //主线程
      //countdown操作
      new Thread( new Runnable(){ public void run(){ countDownLatch .countdown() }}).start();
      new Thread( new Runnable(){ public void run(){ countDownLatch .countdown() }}).start();
     
     //await操作,等待countdownLatch变成0,才继续执行
      new Thread( new Runnable(){ public void run(){ countDownLatch .await() }}).start();
    }
    

    相关countlatchdown代码可以参考:https://blog.csdn.net/simonchi/article/details/47150173

    CyclicBarrier

    image.png

    由图我们知道,所有调用了CyclicBarrier.await()的线程会被阻塞,知道所有在Cyclic上的线程都await了后会整体释放一起恢复执行。其具体表现是等一拨人筹齐了再走。

    其交互伪代码为:

    CyclicBarrier cb = new CyclicBarrier(3)
      new Thread( new Runnable(){ public void run(){ cb.await() }}).start();
      new Thread( new Runnable(){ public void run(){ cb.await()}}).start();
      //如果没有第三个线程执行cb.await()的话,那么 第一第二个线程永远在等待(除非被interrupted)
    

    Exchanger

    Exchange用于另个线程之间交换数据,如果一个线程thread1执行了Exchanger.exchange()方法另一个线程thread2还没有,那么thread1会被阻塞。其交互图如下:


    image.png

    Exchanger经常用于两个线程交换队列数据。

    Final Exchanger<List<Integer>> exchanger = new Exchanger<List<Integer>>();
    //两个线程交换队列
    thread1 = new Thread
    {
        new  Runnabler(){
           .......
            list1 =new Arraylist<String>();
            list1 = exchanger.exchanger(list1)
       }
    }.start()
    
    thread2 = new Thread
    {
        new  Runnabler(){
           .......
            list2 =new Arraylist<String>();
            list2 = exchanger.exchanger(list2)
       }
    }.start()
    

    Semaphore

    信号量用于控制线程之间的并发,比如5台机器8个工人操作每台机器只能被一个工人操作。那么可以通过semaphore来操作。

    main(){
    Semaphore semaphore = new Semaphore(5);
      new Runnable()
     {
       semaphore.acquire();//如果没有获取到线程阻塞
       .......do job....
      semaphore.release();
     }
    }
    //注意 semaphore.acquire()没有获取的话阻塞,如果不想阻塞可以替换成semaphore.tryacquire();//如果获取成功返回true,没有获取成功返回false
    

    wait, notify,notifyAll

    查看jdk Object.java 查看了释义,七对wait和notify解释如下:
    wait:cause the current thread to wait until another thread to invoke the notify/notifyall method of this object.
    1.首先什么是current thread即当前正在执行queue.wait()的线程 currentThread1。
    2.我们需要通过另外一个线程 调用 queue.notify()来唤醒在 queue对象上等待的线程(有个等待队列)。

    写代码需要注意以下几点:
    1.wait和notify用于线程间协同,它是一个线程共享对象,所以需要加锁或者其他机制保证线程间可见和同步。
    2.在调用wait的时候,要先判断是否条件不够。
    具体以生产者消费者模型:

    producer:
    synchronized(queue)
    {
       condition = hold
       queue.notifyall();
       
        // 唤醒等待的线程(consumer线程,告诉他们有工作可以做了)去取队列数据工作
    }
    
    consumer:
    synchronized(queue)
    {
     while (&lt;condition does not hold&gt;) //该consumer下次任务同样要判断
            queue.wait(timeout, nanos);
           // Perform action appropriate to condition  ->这个是被唤醒之后执行的吧。
         }
       }
    }
    

    疑问:要consumer线程一直while检查条件,那么意思是说queue.wati()后consumer线程还会去进行下一次循环遍历么?

    相关文章

      网友评论

          本文标题:[099]技术-jdk中的多线程相关的基本数据结构

          本文链接:https://www.haomeiwen.com/subject/zxrrgxtx.html