diff --git a/README.md b/README.md
index a83294429121e1c4ee2e228531623c66d84b14ea..1bc3b2235789dad7a7e4251c47df916eece8af96 100644
--- a/README.md
+++ b/README.md
@@ -47,3 +47,7 @@ Here you find decorators, functions and classes that help you implement caching
 
 ## qutil.io
 User input related functions like `query_yes_no`.
+
+## qutil.parallel
+Functions and classes related to parallel execution i.e. multi-threading, multi-processing and asyncio.
+There is a class for periodic callbacks from another thread `ThreadedPeriodicCallback`.
diff --git a/qutil/parallel.py b/qutil/parallel.py
new file mode 100644
index 0000000000000000000000000000000000000000..08483bbc24b9a5178ad6ed4730505ce169d9a9b6
--- /dev/null
+++ b/qutil/parallel.py
@@ -0,0 +1,35 @@
+import threading
+import time
+
+
+class ThreadedPeriodicCallback:
+    """Periodically call the given function. Dont forget to call start. You can change the period while it runs.
+    Be aware that your callback needs to be thread safe. This means you need to make sure that the state there is always
+    consistent.
+
+    Example:
+        >>> pcb = ThreadedPeriodicCallback(1., lambda: print('my function'))
+        >>> pcb.start()
+
+        >>> pcb.stop()
+    """
+    def __init__(self, period: float, callback: callable):
+        self._stop = False
+        self.period = period
+        self.callback = callback
+        self.thread = threading.Thread(target=self._run)
+
+    def _run(self):
+        while not self._stop:
+            self.callback()
+            time.sleep(self.period)
+
+    def stop(self):
+        self._stop = True
+        self.thread.join()
+
+    def start(self):
+        self.thread.start()
+
+    def __del__(self):
+        self.stop()