DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

  1. DZone
  2. Coding
  3. Java
  4. Async Programming in Java: Part I

Async Programming in Java: Part I

Let's discuss asynchronous programming in Java and various ways to achieve it, starting with Thread, Runnable, and Callable.

By 
Venkatesh Rajendran user avatar
Venkatesh Rajendran
DZone Core CORE ·
Jan. 09, 21 · Tutorial
Likes (47)
Comment (0)

Save
Tweet
Share
18.45K Views

Join the DZone community and get the full member experience.

Join For Free

As a backend engineer, we face situations to process the data asynchronously. Today let's see how it's done in java and various way to do it.

Starting from Thread, Runnable, Callable<T>, Future<T> (and its extended ScheduledFuture<T>), CompletableFuture<T>, and of course, ExecutorService and ForkJoinPool. We will see all of them, but one by one.

Thread

The very basic yet so powerful component of Java concurrency is Thread. The Thread of Java is actually associated with the Thread of the Operating System. The very basic way to create a Thread is by extending it and overriding the run method:

Java
 




x


 
1
public class TestThread extends Thread{
2

          
3
    @Override
4
    public void run() {
5
        // Logic
6
        super.run();
7
    }
8
    
9
}
10

          
11
TestThread t = new TestThread();
12
// starts thread
13
t.start();// starting the thread, causes the run method be called



Starting the thread causes the run() method to be called.
You may ask; yes, Thread has tons of other methods that can be overridden:

  • In most cases, we don't want to override other methods of the thread. 
  • Once we extend theThreadclass, the extending class losses its ability to extend further as Java does not support multiple inheritances.
  • Each thread has its own object when we extend it, and it's not good for memory health when there are tons of Objects of the extendedThreadcreated.

Java addresses these issues with the Runnable interface. In fact, Thread has an overloaded method that takes Runnable.

Runnable

Runnable is an interface that has only one method: run(). Yes, Runnable is a functional interface, and its instance can be created with the lambda function. Yet it's an easy way to do this; for complex things, we might like to implement it. See the difference here. It's all about the requirement:

Java
 




x


 
1
// With lambda
2
    Runnable runnable = ()->System.out.println("I'm a runnable from lambda.");
3

          
4
// With implemention, we can hold the data and related stuff that we want to process.
5
// Otherwise we got to manage them in the launching thread
6
public class RunnableImplemented implements Runnable{
7

          
8
    List<Object> mayBeAListOfData;
9
    Object mayBeAService;
10
    Object mayBeADao;
11
    
12
    public RunnableImplemented(List<Object> mayBeAListOfData, 
13
                               Object mayBeAService, Object mayBeADao) {
14
        super();
15
        this.mayBeAListOfData = mayBeAListOfData;
16
        this.mayBeAService = mayBeAService;
17
        this.mayBeADao = mayBeADao;
18
    }
19

          
20
    @Override
21
    public void run() {
22
        // code logic
23
    }
24
    
25
}



Though Runnable has arun()method, it's not a Thread but just a Java class until it's taken control by (passed to) Thread. The starting of the thread causes the runnable object'srun()method to be called.

Java
 




xxxxxxxxxx
1


 
1
public class TestThread {
2

          
3
    private static Runnable runnable = ()->System.out.println("I'm a runnable from lambda.");
4
    
5
    public static void main(String[] args) {
6
        Thread t = new Thread(runnable);// takes runnable here
7
        t.start();
8
    }
9
}



Cool, we learnt how to create threads with Thread as well as Runnable. But have you noticed Thread (or Runnable either),

  • TheRunnablemethod doesn't return anything?
  • Also doesn't have exception handling. You have to surround your code that throws an Exception with try and catch block

Yep, Java got it solved in version 1.5, and it's Callable<V>.

Callable<V>

Callable is a generic interface. Why? The type of the return value as the generic type.  Callable is too a functional interface andcall()is the only method, a no-argument method that throws Exception and returns generic type value.

The implementing Callable is very similar to Runnable:

Java
 




x
9
10


 
1
private static Callable<Integer> callable = ()-> {
2
  String data = "I'm in callable.";
3
  System.out.println();
4
  return data.length();
5
};
6
    
7
public static void main(String[] args) {
8
  ExecutorService executor = Executors.newSingleThreadExecutor();
9
  Future<Integer> callFuture = executor.submit(callable);
10
  Integer integer = callFuture.get();
11
}



See here, thecallmethod processes the data and returns a value that can be collected post-execution. But is there a huge difference in invoking it? We use ExecutorService to invoke and Future to hold the result. Let's talk about why.

As you can see, there is no controlled behavior of creating and running the Threads (Runnable or Callable too). We may want to control the number of threads running at a time as each of them associated with OS's threads. The number of Threads we run should be lesser than the number of available CPU cores. All together, Java solves it by ExecutorService interface. 

I think it's really a lot for today. Maybe in Part II, we will discuss Executors and different types of ExecutorService, and the Future<V> interface.


Java (programming language)

Opinions expressed by DZone contributors are their own.

Partner Resources

×

    Java Spotlight

  • Async Programming in Java: Part I

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!