# Report - Multithreading Assignment ## 1. Difference Between start() and run() In Java, both `start()` and `run()` are related to threads, but they behave differently. When we call the `run()` method directly, no new thread is created. The method runs like a normal method in the current thread, usually the main thread. When we call the `start()` method, Java creates a new thread and then executes the `run()` method inside that new thread. Example: ```java Thread t1 = new Thread(() -> { System.out.println("Thread 1: " + Thread.currentThread().getName()); }); Thread t2 = new Thread(() -> { System.out.println("Thread 2: " + Thread.currentThread().getName()); }); t1.run(); t2.start(); Possible output: text Thread 1: main Thread 2: Thread-0 In this output, `t1.run()` runs in the main thread, but `t2.start()` runs in a separate thread. So, the main difference is: - `run()` executes the code normally in the current thread. - `start()` creates a new thread and runs the code concurrently. ## 2. Daemon Threads A daemon thread is a background thread that does not prevent the program from exiting. If only daemon threads are still running and all normal user threads finish, the JVM stops the program automatically. Example: java Thread daemonThread = new Thread(() -> { while (true) { System.out.println("Daemon thread is running..."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); daemonThread.setDaemon(true); daemonThread.start(); System.out.println("Main thread finished."); Possible output: text Main thread finished. Daemon thread is running... The daemon thread may stop immediately after the main thread finishes because the JVM does not wait for daemon threads. If we remove this line: java daemonThread.setDaemon(true); then the thread becomes a normal user thread. In that case, the program may not stop because the infinite loop keeps running. Real-life examples of daemon threads: - Garbage Collector in Java - Background monitoring tasks - Auto-save services - Log cleanup tasks - Background cache cleanup Daemon threads are useful for background tasks that should not block the application from closing. ## 3. Lambda Expressions and Runnable The syntax `() -> { ... }` is called a lambda expression. In Java, lambda expressions can be used to write shorter code for functional interfaces such as `Runnable`. Traditional way: java Runnable task = new Runnable() { @Override public void run() { System.out.println("Task is running"); } }; Thread thread = new Thread(task); thread.start(); Lambda way: java Runnable task = () -> { System.out.println("Task is running"); }; Thread thread = new Thread(task); thread.start(); Output: text Task is running Both versions do the same thing, but the lambda version is shorter and cleaner. The lambda expression is useful because `Runnable` has only one abstract method: `run()`. Main differences: - Traditional implementation needs an anonymous class. - Lambda expression uses shorter syntax. - Lambda expression makes the code easier to read. - Both can be used to create and run threads. ## 4. Practical Part Explanation In the practical part of this assignment, a simulated download manager was implemented using multithreading. The file is divided into several chunks. Each chunk is downloaded by a separate worker thread. Each worker updates its own `ChunkStatus`. The `ProgressMonitor` runs separately and checks the progress of all chunks. It calculates the total downloaded size and prints the progress percentage until the download reaches 100%. The configuration values are read from `download_config.txt`, such as file size, number of chunks, delay range, download step range, and monitor delay. This project demonstrates the basic concepts of multithreading, including: - Creating multiple threads - Running tasks concurrently - Monitoring shared progress - Waiting for threads to finish - Simulating a real download manager