QTimer线程安全的方法是'isActive()'吗?

时间:2017-05-08 17:12:07

标签: c++ multithreading qt thread-safety qtimer

我目前正在考虑QTimer实施的线程安全性。

在我的应用程序中,我使用bool isActive()方法检查计时器是否正在运行。由于我打算也从其他线程使用这种方法,我的想法转到了线程安全考虑。

根据我的研究,方法bool isActive()不是线程安全的。

以下是我的假设:

QTimerQTimer source code)的实现表明bool isActive()只检查成员变量int id;是否大于0:

inline bool isActive() const { return id >= 0; }

此成员变量在构造函数中使用INV_TIMER初始化,-1int QObject::startTimer(int interval)的定义。启动计时器时,它将被设置为/*! \overload start() Starts or restarts the timer with the timeout specified in \l interval. If \l singleShot is true, the timer will be activated only once. */ void QTimer::start() { if (id != INV_TIMER) // stop running timer stop(); nulltimer = (!inter && single); id = QObject::startTimer(inter); } 的返回值。

isActive()

QTimer::start()期间从另一个帖子执行对bool isActive()的调用时,我认为class SensorControl : public QObject { Q_OBJECT public: SensorControl(); // inits and interval-settings are done at implementation bool Start() { QMutexLocker lock(&m_mutexTimer); return m_pTimer->start(); } void Stop() { QMutexLocker lock(&m_mutexTimer); return m_pTimer->stop(); } bool IsMeasuring() const { QMutexLocker lock(&m_mutexTimer); return m_pTimer->isActive(); } private: QMutex m_mutexTimer; QTimer* m_pTimer; }; 的返回值可能无效。

我很感激能够验证我的假设的人的意见。

为了达到线程安全性,我只需使用互斥锁将我的调用打包到计时器,就像下面显示的代码片段一样。

/**
 * 
 */
package com.shashank.java8.parallel_stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author pooja
 *
 */
public class Sample {

    public static int processUrl(String url) {

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Running Thread " + Thread.currentThread());
        return url.length();
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        usingExecutor();
        usingParallelStream();
    }

    public static void usingParallelStream() {

        Date start = new Date();
        // TODO Auto-generated method stub
        int total = buildUrlsList().parallelStream().mapToInt(Sample::processUrl).reduce(0, Integer::sum);
        Date end = new Date();
        System.out.println(total);
        System.out.println((end.getTime() - start.getTime()) / 1000);

    }

    public static void usingExecutor() throws Exception {
        Date start = new Date();
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        List<Future> futures = new ArrayList<>();

        for (String url : buildUrlsList()) {
            futures.add(executorService.submit(() -> processUrl(url)));

        }

        // iterate through the future
        int total = 0;
        for (Future<Integer> future : futures) {
            total += future.get();
        }
        System.out.println(total);
        Date end = new Date();
        System.out.println((end.getTime() - start.getTime()) / 1000);

    }

    public static List<String> buildUrlsList() {
        return Arrays.asList("url1", "url2", "url3", "url4", "url5", "url6", "url7", "url8", "url9");

    }

}

1 个答案:

答案 0 :(得分:1)

如果您想从另一个线程调用QTimer::isActive,那么您的解决方案看起来很安全。 isActive仅访问id成员变量,因此您需要互斥保护对id的所有写入以及从您的线程中读取id。您为isActivestop执行了此操作,因此看起来不错。

请注意,如果您曾调用QTimer写入id的其他方法,则会得到未定义的行为。因此,请注意不要调用QTimer::setInterval()QTimer::~QTimer()(!)等内容。也不要使用单一计时器,因为它会写入id中的QTimer::timerEvent()

通常包装现有类并添加互斥锁是危险的,这是否有效取决于所述类的内部,并且很难检查所有情况。此外,内部可能在下一个Qt版本中发生变化,可能在下一个版本中QTimer::timerEvent()将无条件地更改id,并且您的解决方案不再是线程安全的。

所以,虽然你的方法有效,但总的来说我会反对它。