diff --git a/7-0-java-concurrency/7-0-0-hello-threads/README.md b/7-0-java-concurrency/7-0-0-hello-threads/README.md
new file mode 100644
index 000000000..c698aaa65
--- /dev/null
+++ b/7-0-java-concurrency/7-0-0-hello-threads/README.md
@@ -0,0 +1,7 @@
+# Java concurrency
+Start learning concurrency in Java by writing simple functions using Threads πͺ
+
+### Objectives
+TODO
+#### π First time here? β [See Introduction](https://github.com/bobocode-projects/java-fundamentals-course/tree/main/0-0-intro#introduction)
+#### β‘οΈ Have any feedback? β [Please fill the form ](https://forms.gle/TPSCpZAMZvNXYCoA6)
\ No newline at end of file
diff --git a/7-0-java-concurrency/7-0-0-hello-threads/pom.xml b/7-0-java-concurrency/7-0-0-hello-threads/pom.xml
new file mode 100644
index 000000000..07f1fe6c7
--- /dev/null
+++ b/7-0-java-concurrency/7-0-0-hello-threads/pom.xml
@@ -0,0 +1,18 @@
+
+
+
+ 7-0-java-concurrency
+ com.bobocode
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ 7-0-0-hello-threads
+
+
+ 11
+ 11
+
+
\ No newline at end of file
diff --git a/7-0-java-concurrency/7-0-0-hello-threads/src/main/java/com/bobocode/concurrency/HelloThreads.java b/7-0-java-concurrency/7-0-0-hello-threads/src/main/java/com/bobocode/concurrency/HelloThreads.java
new file mode 100644
index 000000000..10558fc0a
--- /dev/null
+++ b/7-0-java-concurrency/7-0-0-hello-threads/src/main/java/com/bobocode/concurrency/HelloThreads.java
@@ -0,0 +1,89 @@
+package com.bobocode.concurrency;
+
+import com.bobocode.util.ExerciseNotCompletedException;
+import lombok.SneakyThrows;
+
+import java.util.List;
+
+import static java.lang.Thread.State;
+
+/**
+ * {@link HelloThreads} provide a simple API for working with Java threads. A {@link Thread} class represents a key
+ * concept in Java Concurrency. So this class is meant to teach you the basics like creating a thread or checking its
+ * state.
+ *
+ * todo: implement each method according to javadoc and verify your impl by running {@link HelloThreadsTest}
+ *
+ * @author Taras Kuzub
+ */
+public class HelloThreads {
+
+ /**
+ * Receives a {@link Runnable} parameter that holds the logic and creates a {@link Thread} instance based on it.
+ *
+ * @param runnable the code you want to run in new thread
+ * @return a new thread
+ */
+ public static Thread createThread(Runnable runnable) {
+ throw new ExerciseNotCompletedException();
+ }
+
+ /**
+ * Receives a {@link Thread} parameter created based on {@link Runnable},
+ *
+ * @param thread the code you want to run
+ */
+ public static void startThread(Thread thread) {
+ throw new ExerciseNotCompletedException();
+ }
+
+ /**
+ * Receives a {@link Thread} parameter created based on {@link Runnable},
+ * and return {@link String} that contains the name this thread
+ *
+ * @param thread the code you want run
+ * @return the name thread
+ */
+ public static String getThreadName(Thread thread) {
+ throw new ExerciseNotCompletedException();
+ }
+
+ /**
+ * Receives a {@link Thread} parameter created based on {@link Runnable},
+ * and return a {@link State} that contains the state this thread
+ *
+ * @param thread the code you want run
+ * @return the thread state
+ */
+ public static State getThreadState(Thread thread) {
+ throw new ExerciseNotCompletedException();
+ }
+
+ /**
+ * Receives a {@link Thread} parameter created based on {@link Runnable},
+ * start and wait when thread completed
+ *
+ * @param thread the code you want run
+ */
+ @SneakyThrows
+ public static void waitForThreadToComplete(Thread thread) {
+ throw new ExerciseNotCompletedException();
+ }
+
+ /**
+ * Receives three {@link Thread} parameters created based on {@link Runnable}
+ * start all threads and wait when all threads completed.
+ * You should return {@link List} of threads that have already been completed
+ *
+ * @param thread1 the code you want run
+ * @param thread2 the code you want run
+ * @param thread3 the code you want run
+ *
+ * @return the list of running threads
+ */
+ @SneakyThrows
+ public static List getListThreads(Thread thread1, Thread thread2, Thread thread3) {
+ throw new ExerciseNotCompletedException();
+ }
+}
+
diff --git a/7-0-java-concurrency/7-0-0-hello-threads/src/test/java/com/bobocode/concurrency/HelloThreadsTest.java b/7-0-java-concurrency/7-0-0-hello-threads/src/test/java/com/bobocode/concurrency/HelloThreadsTest.java
new file mode 100644
index 000000000..21ec2241b
--- /dev/null
+++ b/7-0-java-concurrency/7-0-0-hello-threads/src/test/java/com/bobocode/concurrency/HelloThreadsTest.java
@@ -0,0 +1,107 @@
+package com.bobocode.concurrency;
+
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.*;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import static java.lang.Thread.State.RUNNABLE;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.mockito.Mockito.*;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class HelloThreadsTest {
+
+ private Queue concurrentLinkedQueue;
+
+ @BeforeEach
+ void setup() {
+ concurrentLinkedQueue = new ConcurrentLinkedQueue();
+ }
+
+ @SneakyThrows
+ @Test
+ @Order(1)
+ void createThread() {
+ var thread = HelloThreads.createThread(() -> concurrentLinkedQueue.add(5));
+
+ thread.start();
+
+ assertAll(
+ () -> assertThat(concurrentLinkedQueue).hasSize(1),
+ () -> assertThat(concurrentLinkedQueue.element().intValue()).isEqualTo(5)
+ );
+ }
+
+ @SneakyThrows
+ @Test
+ @Order(2)
+ void startThread() {
+ var thread = new Thread(() -> concurrentLinkedQueue.add(5));
+
+ HelloThreads.startThread(thread);
+
+ assertAll(
+ () -> assertThat(concurrentLinkedQueue).hasSize(1),
+ () -> assertThat(concurrentLinkedQueue.element().intValue()).isEqualTo(5)
+ );
+ }
+
+ @SneakyThrows
+ @Test
+ @Order(3)
+ void getThreadName() {
+ var thread = new Thread(() -> concurrentLinkedQueue.add(5), "Hello Thread");
+ var name = HelloThreads.getThreadName(thread);
+
+ assertThat(name).isEqualTo("Hello Thread");
+ }
+
+ @SneakyThrows
+ @Test
+ @Order(4)
+ void getThreadState() {
+ var thread = new Thread(() -> concurrentLinkedQueue.add(5));
+
+ var state = HelloThreads.getThreadState(thread);
+
+ assertThat(state).isEqualTo(RUNNABLE);
+ }
+
+ @SneakyThrows
+ @Test
+ @Order(5)
+ void waitForThreadToComplete() {
+ var thread = mock(Thread.class);
+
+ HelloThreads.waitForThreadToComplete(thread);
+
+ assertAll(
+ () -> verify(thread, times(1)).start(),
+ () -> verify(thread, times(1)).join()
+ );
+ }
+
+ @SneakyThrows
+ @Test
+ @Order(6)
+ void getListThreads() {
+ var thread1 = mock(Thread.class);
+ var thread2 = mock(Thread.class);
+ var thread3 = mock(Thread.class);
+
+ var threads = HelloThreads.getListThreads(thread1, thread2, thread3);
+
+ assertAll(
+ () -> assertThat(threads).hasSize(3),
+ () -> verify(thread1, times(1)).start(),
+ () -> verify(thread1, times(1)).join(),
+ () -> verify(thread2, times(1)).start(),
+ () -> verify(thread2, times(1)).join(),
+ () -> verify(thread3, times(1)).start(),
+ () -> verify(thread3, times(1)).join()
+ );
+ }
+}
\ No newline at end of file
diff --git a/7-0-java-concurrency/pom.xml b/7-0-java-concurrency/pom.xml
new file mode 100644
index 000000000..21d3d661e
--- /dev/null
+++ b/7-0-java-concurrency/pom.xml
@@ -0,0 +1,30 @@
+
+
+ 4.0.0
+ pom
+
+ 7-0-0-hello-threads
+
+
+
+ java-fundamentals-course
+ com.bobocode
+ 1.0-SNAPSHOT
+
+
+ 7-0-java-concurrency
+
+ 11
+ 11
+
+
+
+
+ com.bobocode
+ java-fundamentals-util
+ 1.0-SNAPSHOT
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 824dae046..3198b50c5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,7 @@
4-0-object-oriented-programming
5-0-functional-programming
6-0-test-driven-development
+ 7-0-java-concurrency
java-fundamentals-util
lesson-demo