In the end, big universities realized that Java was a lousy language if used for introductory programming
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.
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.
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).
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.
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.
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.
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.
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();
In this article, we have a method for writing multithreaded code in Java. Include:
Hope the article can help you somewhat!