Java笔记-对CountDownLatch的理解(对比Qt中的QSemaphore)含实例

首先在CountDownLatch,这个东西基本上和信号量是一样的,这个CountDownLatch要设置一个初值,这个值一般是个正值,可以对这个CountDownLatch进行countDown()也就是减1,当减少为0时,await()函数就会从阻塞变成就绪态。

 

下面是Java代码,举个例子,此例子来源于博客园大神,3个工人干活,3个都干完后,老版才开始检查工作,运行截图如下:

源码如下:

 Boss.java

package cn.it1995;

import java.util.concurrent.CountDownLatch;

public class Boss implements Runnable{

    private CountDownLatch downLatch;

    public Boss(CountDownLatch downLatch){

        this.downLatch = downLatch;
    }


    public void run() {

        System.out.println("老版在等待所有工人干完活....");

        try {
            this.downLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("工人都干完活了,老版开始检查");
    }
}

Worker.java

package cn.it1995;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

    public static void main(String[] args){

        ExecutorService executorService = Executors.newCachedThreadPool();

        CountDownLatch latch = new CountDownLatch(3);

        Worker w1 = new Worker(latch, "张三");
        Worker w2 = new Worker(latch, "李四");
        Worker w3 = new Worker(latch, "王二");

        Boss boss = new Boss(latch);

        executorService.execute(w1);
        executorService.execute(w2);
        executorService.execute(w3);
        executorService.execute(boss);

        executorService.shutdown();
    }
}

Main.java

package cn.it1995;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class Worker implements Runnable{

    private CountDownLatch downLatch;
    private String name;

    public Worker(CountDownLatch downLatch, String name){

        this.downLatch = downLatch;
        this.name = name;
    }

    private void doWork(){

        System.out.println(this.name + " 正在干活...");
    }

    public void run() {

        this.doWork();

        try{

            TimeUnit.SECONDS.sleep(new Random().nextInt(10));
        }
        catch(InterruptedException e){

            e.printStackTrace();
        }
        this.downLatch.countDown();
        System.out.println(this.name + " 干完活了!");
    }
}

源码打包下载地址:

https://github.com/fengfanchen/Java/tree/master/CountDownLatchDemo

 

这里我们来对比下Qt里面的信号量QSemaphore,其实上面那个CountDownLatch基本上等同于信号量,只是基本上啊,不过信号量可以干很多东西,不限于上面的。

程序运行截图如下:

源码如下:

Boss.h

#ifndef BOSS_H
#define BOSS_H

#include <QObject>

QT_BEGIN_NAMESPACE
class QSemaphore;
QT_END_NAMESPACE

class Boss : public QObject
{
    Q_OBJECT
public:
    Boss(QSemaphore *sem, QObject *parent = nullptr);
    ~Boss();

public slots:
    void doWork();

private:
    QSemaphore *m_sem;

};

#endif // BOSS_H

Worker.h

#ifndef WORKER_H
#define WORKER_H

#include <QObject>

QT_BEGIN_NAMESPACE
class QSemaphore;
QT_END_NAMESPACE

class Worker : public QObject
{
    Q_OBJECT
public:
    Worker(QSemaphore *sem, QString name, QObject *parent = nullptr);
    ~Worker();

public slots:
    void doWork();

private:
    QString m_name;
    QSemaphore *m_sem;
};

#endif // WORKER_H

Boss.cpp

#include "Boss.h"
#include <QThread>
#include <QDebug>
#include <QSemaphore>

Boss::Boss(QSemaphore *sem, QObject *parent) : QObject(parent)
{
    m_sem = sem;
}

Boss::~Boss()
{
    qDebug() << "BOSS 析构";
}

void Boss::doWork()
{
    qDebug() << "子线程[" << QThread::currentThread() << "]: " << "BOSS" << " 等待所有人完成工作...";
    m_sem->acquire(1);
    qDebug() << "子线程[" << QThread::currentThread() << "]: " << "BOSS" << " 开始检测工作!!!";
}

main.cpp

#include <QCoreApplication>
#include <QSemaphore>
#include <QThread>
#include <QDebug>
#include "Worker.h"
#include "Boss.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QSemaphore sem(-2);

    qDebug() <<"主线程[" << QThread::currentThread() << "]: 开始运行";

    QThread thread1;
    QThread thread2;
    QThread thread3;
    QThread thread4;
    Worker worker1(&sem, "张三");
    Worker worker2(&sem, "李四");
    Worker worker3(&sem, "王二");
    Boss boss(&sem);
    worker1.moveToThread(&thread1);
    worker2.moveToThread(&thread2);
    worker3.moveToThread(&thread3);
    boss.moveToThread(&thread4);

    QObject::connect(&thread1, &QThread::started, &worker1, &Worker::doWork);
    QObject::connect(&thread1, &QThread::finished, &worker1, &QObject::deleteLater);

    QObject::connect(&thread2, &QThread::started, &worker2, &Worker::doWork);
    QObject::connect(&thread2, &QThread::finished, &worker2, &QObject::deleteLater);

    QObject::connect(&thread3, &QThread::started, &worker3, &Worker::doWork);
    QObject::connect(&thread3, &QThread::finished, &worker3, &QObject::deleteLater);

    QObject::connect(&thread4, &QThread::started, &boss, &Boss::doWork);
    QObject::connect(&thread4, &QThread::finished, &boss, &QObject::deleteLater);

    thread1.start();
    QThread::sleep(1);  //为了产生不同的随机种子
    thread2.start();
    QThread::sleep(1);  //为了产生不同的随机种子
    thread3.start();
    thread4.start();

    return a.exec();
}

Worker.cpp

#include "Worker.h"
#include <QSemaphore>
#include <QThread>
#include <QTime>
#include <QDebug>

Worker::Worker(QSemaphore *sem, QString name, QObject *parent) : QObject(parent)
{
    m_sem = sem;
    m_name = name;
}

Worker::~Worker()
{
    qDebug() << m_name << " 析构";
}

void Worker::doWork()
{
    qsrand(QTime::currentTime().msec() + QTime::currentTime().second()*1000);
    qDebug() << "子线程[" << QThread::currentThread() << "]: " << m_name << " 正在干活...";
    QThread::sleep(qrand() % 10 + 5);
    qDebug() << "子线程[" << QThread::currentThread() << "]: " << m_name << " 活干完了!!!";
    m_sem->release(1);
}

源码打包下载地址:

https://github.com/fengfanchen/Qt/tree/master/SemaphoreTest

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页