4 ways to write multi-threaded code in Java

Multithreading is a method of writing code to execute multiple tasks in parallel. Java offers great support for multi-threaded code writing right from Java 1.0 version. Recent improvements in Java have increased the number of ways that code is structured to combine multiple threads in Java programs.

Multithreading is a method of writing code to execute multiple tasks in parallel. Java offers great support for multi-threaded code writing right from Java 1.0 version. Recent improvements in Java have increased the number of ways that code is structured to combine multiple threads in Java programs.

In this article, TipsMake.com compares several options for writing multithreaded code, hoping readers can choose for themselves a suitable way to apply in their next Java project.

  1. How to fix the error does not install Java

  2. In the end, big universities realized that Java was a lousy language if used for introductory programming

4 ways to write multi-threaded code in Java Picture 14 ways to write multi-threaded code in Java Picture 1

Method 1: Expand the Thread class

Java provides a Thread class that can be extended to run run () . run () is the place to perform the task. When you want to start a task in its own thread, you can create an instance in this class and call start () . This will start thread execution and run to complete (or terminate) the task.

4 ways to write multi-threaded code in Java Picture 24 ways to write multi-threaded code in Java Picture 2

This is a simple Thread class that performs a sleep task for a specified period of time as a way to simulate a long-running operation.

 public class MyThread extends Thread { private int sleepFor; public MyThread(int sleepFor) { this.sleepFor = sleepFor; } @Override public void run() { System.out.printf("[%s] thread startingn", Thread.currentThread().toString()); try { Thread.sleep(this.sleepFor); } catch(InterruptedException ex) {} System.out.printf("[%s] thread endingn", Thread.currentThread().toString()); } } 

Create an instance of this Thread class by giving it the number of milliseconds to sleep.

 MyThread worker = new MyThread(sleepFor); 

Launch the worker thread process by calling its start () method. This method will return the control immediately to the caller without waiting for the thread to terminate.

 worker.start(); System.out.printf("[%s] main threadn", Thread.currentThread().toString()); 

And this is the output when running this code. It indicates that the main thread is printed before the worker thread completes.

 [Thread[main,5,main]] main thread [Thread[Thread-0,5,main]] thread starting [Thread[Thread-0,5,main]] thread ending 

Because there is no command after starting the worker thread, the main thread will wait for the worker thread to end before the program exits. This allows the worker thread to complete all of its tasks.

Method 2: Use Thread Instance with Runnable

Java also provides an interface called Runnable, which can be implemented by a worker class to execute the task in its run () method. This is another way to create worker classes instead of extending the Thread class (described above).

4 ways to write multi-threaded code in Java Picture 34 ways to write multi-threaded code in Java Picture 3

This is how to implement the worker class with Runnable instead of expanding Thread.

 public class MyThread2 implements Runnable { 
// same as above
}

The advantage of this way the worker class can extend a specific class by domain in a class hierarchy. What does that mean? For example, you have a Fruit class that contains common characteristics that belong to the fruit. Now you want to make a Papaya class with certain characteristics of fruit. You can do that with the following code:

 public class Fruit { // fruit specifics here } public class Papaya extends Fruit { // override behavior specific to papaya here } 

Now suppose there are some time-consuming tasks that Papaya needs to support, which can be done in a separate stream. This case can be handled by requiring the Papaya class to execute Runnable and provide the run () method where this task is executed.

 public class Papaya extends Fruit implements Runnable { // override behavior specific to papaya here @Override public void run() { // time consuming task here. } } 

To start the worker thread, create an instance of the worker class and assign it to the Thread instance during creation. When the Thread's start () method is called, the task will execute in a separate thread.

 Papaya papaya = new Papaya(); // set properties and invoke papaya methods here. Thread thread = new Thread(papaya); thread.start(); 

And that's a simple way to use Runnable to perform tasks in a thread.

Method 3: Deploy Runnable with ExecutorService

Starting with version 1.5, Java adds ExecutorService as a new model to create and manage threads in a program. It generalizes the concept of thread deployment by abstracting the creation of threads.

This is because you can run multiple tasks in the thread group, using separate threads for each task. As a result, the program can monitor and manage how many threads are used for worker tasks.

4 ways to write multi-threaded code in Java Picture 44 ways to write multi-threaded code in Java Picture 4

Suppose you have 100 worker tasks waiting to be done. If you start a thread for each worker, there will be 100 threads in the program. This can lead to bottlenecks elsewhere in the program. Instead, if using a thread group, 10 pre-allocated threads, 100 tasks will be executed by these threads, one by one, and the program will not be short of resources. In addition, this thread group can be configured to perform additional tasks.

The ExecutorService accepts a Runnable task and runs the task at an appropriate time. The submit () method returns the instance of a class called Future, allowing the caller to track the status of the task. Specifically, the get () method allows the caller to wait until the task completes (and provide the return code, if any).

In the example below, we can create ExecutorService using the static method newSingleThreadExecutor (), to create a single thread to perform tasks. If multiple tasks are submitted while another task is running, ExcecutorService will sort these tasks to be executed after the previous task finishes.

This is an example of the above long description:

 ExecutorService esvc = Executors.newSingleThreadExecutor(); Runnable worker = new MyThread2(sleepFor); Future future = esvc.submit(worker); System.out.printf("[%s] main threadn", Thread.currentThread().toString()); future.get(); esvc.shutdown();  ExecutorService esvc = Executors.newSingleThreadExecutor(); Runnable worker = new MyThread2(sleepFor); Future future = esvc.submit(worker); System.out.printf("[%s] main threadn", Thread.currentThread().toString()); future.get(); esvc.shutdown(); 

Note that, ExecutorService must be properly closed when it is not needed to submit subsequent tasks.

Method 4: Use Callable with ExecutorService

In version 1.5 Java introduced new Callable, quite similar to Runnable. The difference is that the executable method (called call () instead of run ()) can return a value. It can also declare an inserted Exception.

ExecutorService can accept tasks performed as Callable and return Future with the value returned by the method at the end of the task.

4 ways to write multi-threaded code in Java Picture 54 ways to write multi-threaded code in Java Picture 5

This is an example of the Mango class, extending the previously defined Fruit class and performing Callable. A heavy and time-consuming task will be performed in call ().

 public class Mango extends Fruit implements Callable { public Integer call() { // expensive computation here return new Integer(0); } } 

And here is the code to submit an instance of the class to ExcecutorService. The code below also waits until the task completes and prints the value it returns.

 ExecutorService esvc = Executors.newSingleThreadExecutor(); MyCallable worker = new MyCallable(sleepFor); Future future = esvc.submit(worker); System.out.printf("[%s] main threadn", Thread.currentThread().toString()); System.out.println("Task returned: " + future.get()); esvc.shutdown(); 

Which way do you like creating thread?

In this article, we have a method for writing multithreaded code in Java. Include:

  1. Thread class extension is the most basic and is available from Java 1.0.
  2. If you have a class that must extend some other classes in a class hierarchy, Runnable can be implemented.
  3. A more modern facility for creating threads is ExecutorService that can accept the Runnable instance as a task to run. The advantage of this approach is that you can use a thread pool to perform the task. A thread pool protects resources by reusing threads.
  4. Finally, you can also create a task by deploying Callable and submitting the task to ExecutorService.

Hope the article can help you somewhat!

5 ★ | 1 Vote