Commit a99dbbe0 authored by amira.alkatably's avatar amira.alkatably

final commit

parents
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
\ No newline at end of file
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="19" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
# ThreadPool
The `ThreadPool` class is a lightweight and simple implementation of a thread pool in Java. It provides a convenient way to manage and execute concurrent tasks using a fixed number of threads and a task queue. This can be particularly useful in scenarios where parallel processing of tasks is required, such as in web servers, concurrent applications, or any situation where efficient task execution is essential.
## Overview
### Features
- **Concurrency:** Execute multiple tasks concurrently using a specified number of threads.
- **Task Queue:** Manage tasks efficiently with a task queue, preventing overload and optimizing resource usage.
- **Timeout Handling:** Use the `waitUntilAllTaskFinished` method to wait for all tasks to finish within a specified timeout. If the timeout is reached, the thread pool is stopped.
- **Graceful Shutdown:** Stop the thread pool using the `stop` method, gracefully interrupting all running threads.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>PP-03-HW</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>19</maven.compiler.source>
<maven.compiler.target>19</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
\ No newline at end of file
import java.util.LinkedList;
public class ThreadPool {
private final int numThreads;
private final int queueSize;
private LinkedList<Runnable> taskQueue;
private Thread[] threads;
private boolean isStopped = false;
public boolean isStopped() {
return isStopped;
}
public ThreadPool(int numThreads, int queueSize) {
this.numThreads = numThreads;
this.queueSize = queueSize;
this.taskQueue = new LinkedList<>();
this.threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++) {
threads[i] = new Thread(new PoolThread());
threads[i].start();
}
}
public synchronized void execute(Runnable task) {
if (isStopped ) {
throw new IllegalStateException("ThreadPool is stopped");
}
// Check if the task queue has reached its limit
while (taskQueue.size() >= queueSize) {
try {
System.out.println("Task queue is full. Waiting for space or timeout...");
wait();
} catch (InterruptedException e) {
// Handle interruption if needed
}
}
taskQueue.addLast(task);
notify(); // Notify one waiting thread that a new task is available
}
public synchronized void waitUntilAllTaskFinished(long timeoutMillis) throws InterruptedException {
long endTime = System.currentTimeMillis() + timeoutMillis;
while (System.currentTimeMillis() < endTime) {
long timeRemaining = endTime - System.currentTimeMillis();
if (timeRemaining > 0) {
System.out.println("Waiting for tasks to finish or timeout...");
wait(timeRemaining);
} else {
// Timeout has been reached
break;
}
}
System.out.println("Timeout has been reached, stop the threads.");
stop();
}
public synchronized void stop() {
isStopped = true;
for (Thread thread : threads) {
thread.interrupt(); // Interrupt threads to break out of blocking state
}
}
private class PoolThread implements Runnable {
@Override
public void run() {
while (true) {
synchronized (ThreadPool.this) {
while (taskQueue.isEmpty() && !isStopped ) {
try {
ThreadPool.this.wait(); // Wait for a task to be added
} catch (InterruptedException e) {
// Thread interrupted, check if it's time to exit
if (isStopped ) {
return;
}
}
}
if (isStopped) {
return;
}
// Get and execute the next task
Runnable task = taskQueue.removeFirst();
ThreadPool.this.notify(); // Notify that a slot in the queue is now available
task.run();
}
}
}
}
}
import junit.framework.TestCase;
public class ThreadPoolTest extends TestCase {
public void testExecuteWithLargeNumberOfTasks() throws InterruptedException {
// Create a ThreadPool with 2 threads and a queue size of 5
ThreadPool threadPool = new ThreadPool(2, 5);
// Add tasks to the ThreadPool
for (int i = 0; i < 100; i++) {
int taskId = i;
threadPool.execute(() -> {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getId());
try {
Thread.sleep(100); // Simulate some work
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// Wait for all tasks to finish
threadPool.waitUntilAllTaskFinished(500);
// Stop the ThreadPool
threadPool.stop();
// Assert that the ThreadPool stopped correctly
assertTrue(threadPool.isStopped());
}
public void testWaitUntilAllTaskFinished() throws InterruptedException {
// Create a ThreadPool with 2 threads and a queue size of 200
ThreadPool threadPool = new ThreadPool(2, 200);
// Add tasks to the ThreadPool
for (int i = 0; i < 3; i++) {
int taskId = i;
threadPool.execute(() -> {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getId());
try {
Thread.sleep(500); // Simulate some work
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// Wait for all tasks to finish
threadPool.waitUntilAllTaskFinished(10);
// Assert that the ThreadPool stopped correctly
assertTrue(threadPool.isStopped());
}
public void testThreadPool() throws InterruptedException {
// Create a ThreadPool with 2 threads and a queue size of 5
ThreadPool threadPool = new ThreadPool(2, 5);
// Add tasks to the ThreadPool
for (int i = 0; i < 10; i++) {
int taskId = i;
threadPool.execute(() -> {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getId());
try {
Thread.sleep(100); // Simulate some work
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// Wait for all tasks to finish with a timeout of 1000 milliseconds
threadPool.waitUntilAllTaskFinished(1000);
// Stop the ThreadPool
threadPool.stop();
// Assert that the ThreadPool stopped correctly
assertTrue(threadPool.isStopped());
}
public void testThreadPoolAfterStop() {
// Create a ThreadPool with 1 thread and a queue size of 2
ThreadPool threadPool = new ThreadPool(1, 2);
// Stop the ThreadPool immediately
threadPool.stop();
// Try adding a task after stopping
try {
threadPool.execute(() -> {
System.out.println("This task should not run.");
});
// If the task is added, the test fails
fail("Should not be able to add a task after stopping the ThreadPool");
} catch (IllegalStateException e) {
// Expected exception
}
// Assert that the ThreadPool stopped correctly
assertTrue(threadPool.isStopped());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment