Six different examples of Java code that demonstrate how
to print natural numbers using multiple threads. Below is a summary of the code
and what each one does:
1. Printing Natural Numbers from 1 to 100 Using Two
Threads Without wait or synchronized
This solution uses a shared static flag variable to
alternate between two threads: one prints odd numbers, and the other prints
even numbers.
java
class
OddPrint implements Runnable { static boolean flag = true; public void run() { for (int i = 1; i <= 99;) { if (flag) { System.out.print(i +
"\t"); flag = false; i += 2; } } } } class
EvenPrint implements Runnable { public void run() { for (int i = 2; i <= 100;) { if (!OddPrint.flag) { System.out.print(i +
"\t"); OddPrint.flag = true; i += 2; } } } } public class
NaturalNumber { public static void main(String[] args) { new Thread(new OddPrint()).start(); new Thread(new EvenPrint()).start(); } } |
Output Example:
1 2 3 4 5 6 7
8 9 10 ... 99 100 |
2. Printing Natural Numbers from 1 to 100 Using wait and synchronized
In this example, synchronization and wait/notifyAll are used
to alternate between the threads. The shared lock object ensures that the
threads are properly coordinated.
java
class
OddPrint implements Runnable { static boolean flag = true; private Object lock; public OddPrint(Object lock) { this.lock
= lock; } public void run() { for (int i = 1; i <= 99; i += 2) { synchronized (lock) { while (!flag) { try { lock.wait(); }
catch (InterruptedException e) { } }
System.out.println("Thread 1: " + i); flag = false; lock.notifyAll(); } } } } class
EvenPrint implements Runnable { private Object lock; public EvenPrint(Object lock) { this.lock
= lock; } public void run() { for (int i = 2; i <= 100; i += 2)
{ synchronized (lock) { while (OddPrint.flag) { try { lock.wait(); }
catch (InterruptedException e) { } }
System.out.println("Thread 2: " + i); OddPrint.flag = true; lock.notifyAll(); } } } } public class
NaturalNumberMultiThread { private static Object lock = new
Object(); public static void main(String[] args) { new Thread(new
OddPrint(lock)).start(); new Thread(new
EvenPrint(lock)).start(); } } |
Output Example:
text
Thread 1: 1 Thread 2: 2 Thread 1: 3 Thread 2: 4 ... Thread 1: 99 Thread 2: 100 |
3. Printing Natural Numbers Sequence-Wise Using Three
Threads
This example uses three threads where each thread prints a
sequence of numbers in a round-robin fashion. The threads coordinate using a volatile
counter and a shared object for synchronization.
java
public class
MultipleThreadSequenceWisePrint { private volatile Integer count = 1; private volatile Integer threadIdToRun =
1; private final Object object = new
Object(); public static void main(String[] args) { MultipleThreadSequenceWisePrint
testClass = new MultipleThreadSequenceWisePrint(); Thread t1 = new Thread(testClass.new
Printer(1)); Thread t2 = new Thread(testClass.new
Printer(2)); Thread t3 = new Thread(testClass.new
Printer(3)); t1.start(); t2.start(); t3.start(); } class Printer implements Runnable { private final int threadId; public Printer(int threadId) {
this.threadId = threadId; } @Override public void run() { try { while (count <= 20) { synchronized (object) { if (threadId !=
threadIdToRun) { object.wait(); } else {
System.out.println("Thread " + threadId + " printed
" + count); count++; threadIdToRun =
(threadIdToRun % 3) + 1;
object.notifyAll(); } } } } catch (Exception e) { e.printStackTrace(); } } } } |
Output Example:
text
Thread 1
printed 1 Thread 2
printed 2 Thread 3
printed 3 Thread 1
printed 4 ... Thread 3
printed 18 Thread 1
printed 19 Thread 2
printed 20 |
These examples demonstrate different approaches to
multithreading in Java to achieve ordered execution and synchronization.
4. Print numbers from 1 to 100 using Java's ExecutorService
To print numbers from 1 to 100 using Java's ExecutorService while
ensuring compatibility and efficient execution, you can use a FixedThreadPool
to manage a pool of threads. Here's how you can do it:
Step-by-Step Solution
- Create
a Runnable Task: This task will print the numbers, and each thread in
the pool will handle one task.
- Use
ExecutorService: The ExecutorService is used to manage a pool of
threads and execute tasks asynchronously.
- Submit
Tasks: You submit tasks to the executor, and it schedules them to be
executed by the available threads.
- Shutdown
Executor: After all tasks are submitted, shut down the executor to
ensure the program terminates after all tasks are completed.
Example Code
java
import
java.util.concurrent.ExecutorService; import
java.util.concurrent.Executors; public class
PrintNumbersWithExecutor { public static void main(String[] args) { // Create a fixed thread pool with 2
threads ExecutorService executorService =
Executors.newFixedThreadPool(2); // Submit tasks to the executor for (int i = 1; i <= 100; i++) { int number = i; // Use final or
effectively final variable inside the lambda executorService.submit(() -> {
System.out.println("Number: " + number); }); } // Shut down the executor service executorService.shutdown(); } } |
Explanation:
- ExecutorService:
We create a FixedThreadPool with 2 threads. This allows two threads to
work simultaneously.
- Lambda
Expression: A lambda is used to create a Runnable that prints the
current number. The lambda captures the loop variable i.
- Submitting
Tasks: The loop iterates from 1 to 100, and for each iteration, a task
is submitted to the executor to print that number.
- Shutdown:
After all tasks are submitted, executorService.shutdown() is called to
stop accepting new tasks and eventually shut down the service once all
tasks are completed.
Output
The numbers 1 to 100 will be printed by the threads in the
pool. The order might vary slightly because multiple threads are running
simultaneously, but each number from 1 to 100 will be printed once.
5. To print numbers from 1 to 10 using CompletableFuture
To print numbers from 1 to 10 using CompletableFuture in
Java, you can leverage the asynchronous capabilities of CompletableFuture to
run tasks in parallel or sequentially. Below is a sample code to achieve this:
Example Code
java
import
java.util.concurrent.CompletableFuture; public class
PrintNumbersWithCompletableFuture { public static void main(String[] args) { // Create an array of
CompletableFuture tasks CompletableFuture<Void>[]
futures = new CompletableFuture[10]; for (int i = 1; i <= 10; i++) { final int number = i; // Use
final or effectively final variable futures[i - 1] =
CompletableFuture.runAsync(() -> {
System.out.println("Number: " + number); }); } // Combine all futures and wait for
all to complete CompletableFuture<Void> allOf =
CompletableFuture.allOf(futures); allOf.join(); // Wait for all tasks
to complete } } |
Explanation:
- CompletableFuture.runAsync():
This method is used to run a task asynchronously. It takes a Runnable as
an argument. Each task prints a number from 1 to 10.
- Final
or Effectively Final Variable: The loop variable i is captured inside
the lambda expression, so it needs to be final or effectively final. We
achieve this by assigning it to a new variable number.
- Array
of CompletableFuture: We store each CompletableFuture in an array.
This allows us to later wait for all of them to complete.
- CompletableFuture.allOf():
This method returns a new CompletableFuture that is completed when all the
given CompletableFutures are completed. We then use .join() to block the
main thread until all tasks are finished.
- Output:
The numbers 1 to 10 will be printed asynchronously. The order might vary
slightly due to the nature of asynchronous execution.
6. To print numbers from 1 to 10 using CompletableFuture with
two different threads
To print numbers from 1 to 10 using CompletableFuture with
two different threads, we can divide the task into two parts: one thread prints
the odd numbers, and the other thread prints the even numbers. Here's how you
can achieve this:
Example Code
java
import
java.util.concurrent.CompletableFuture; import
java.util.concurrent.ExecutorService; import
java.util.concurrent.Executors; public class
PrintNumbersWithTwoThreads { public static void main(String[] args) { // Create an executor with two
threads ExecutorService executor =
Executors.newFixedThreadPool(2); // CompletableFuture for printing odd
numbers CompletableFuture<Void>
oddNumbers = CompletableFuture.runAsync(() -> { for (int i = 1; i <= 10; i +=
2) { System.out.println("Odd
Thread: " + i); } }, executor); // CompletableFuture for printing
even numbers CompletableFuture<Void>
evenNumbers = CompletableFuture.runAsync(() -> { for (int i = 2; i <= 10; i +=
2) { System.out.println("Even
Thread: " + i); } }, executor); // Wait for both tasks to complete CompletableFuture<Void>
combinedFuture = CompletableFuture.allOf(oddNumbers, evenNumbers); combinedFuture.join(); // Block until
all tasks are done // Shut down the executor executor.shutdown(); } } |
Explanation:
- ExecutorService
with Two Threads:
- We
create an ExecutorService with a fixed thread pool of 2 threads using Executors.newFixedThreadPool(2).
This ensures that we have exactly two threads executing the tasks.
- CompletableFuture.runAsync():
- We
use runAsync() to create two asynchronous tasks:
- One
for printing odd numbers (1, 3, 5, 7, 9).
- Another
for printing even numbers (2, 4, 6, 8, 10).
- Each
task is executed using the executor with two threads.
- Combining
Futures:
- We
use CompletableFuture.allOf() to wait for both the odd and even number
printing tasks to complete.
- Shutting
Down the Executor:
- After
both tasks are done, we call executor.shutdown() to clean up the
resources.
- Output:
- The
odd and even numbers from 1 to 10 will be printed by two different
threads. The exact order might vary depending on the thread scheduling,
but all numbers from 1 to 10 will be printed.
Two thread print natural number |
0 Comments