Still the Same, But Different: Continuing Comparisons in Java

Didem AĞDOĞAN
6 min readDec 24, 2024

--

Part 2

We are continuing from our previous article. To avoid making it too lengthy, I decided to divide it into two parts.

Runnable vs Thread

Inheriting from the Thread class allows a class to be executed as a thread. In other words, a class that extends the Thread class gains the capability to perform multiple tasks simultaneously through multithreading. This feature enables parallel processing in Java.

Implementing the Runnable interface, on the other hand, defines a class as a "task." However, when a class inherits from the Runnable interface, it is not a thread itself but rather a task that can be executed within a thread. Using Runnable provides a more modular and flexible code structure.

So, What Are the Differences?

  • When we extend the Thread class, we cannot extend any other class because Java does not support multiple inheritance. However, if we implement the Runnable interface, we can still extend another base class if needed.
  • Extending the Thread class creates a unique object for each thread, and each thread is tied to its object. In contrast, implementing the Runnable interface allows multiple threads to share the same object.
  • The Thread class provides several built-in methods like getPriority() and isAlive(). On the other hand, the Runnable interface offers only one method: run().

Although the Thread class provides a simple mechanism for creating and managing threads, it has limitations due to Java's single inheritance constraint. On the other hand, Runnable offers better object-oriented design, reusability, and resource sharing. Therefore, in many scenarios, Runnable is the preferred choice.

Wait vs Sleep

The fundamental difference between these two methods is whether the lock is released or not. The wait() method is used for synchronized synchronization, while sleep() is generally used to temporarily pause a thread based on a timer.

What Are the Differences?

  • The wait() method is defined in the Object class.
  • When the wait() method is called, the thread releases the lock while waiting, allowing other threads to use the same monitor.
  • The sleep() method is defined in the Thread class.
  • When the sleep() method is called, the thread enters a sleep state for the specified duration but does not release the lock. Other threads cannot access the same monitor.

Runnable vs Callable

Both Callable and Runnable are used for performing tasks in a thread, but each has different advantages and use cases.

What Are the Differences?

  • The Callable interface defines the call() method, which returns a result and can throw a checked exception.
  • The Runnable interface only defines the run() method and does not directly support checked exceptions. If an error occurs, exceptions need to be handled with try-catch blocks.
  • Runnable does not return a value and is designed solely for executing tasks.
  • Callable is commonly used with ExecutorService, and results are retrieved through a Future object.

RunAsync vs SupplyAsync

The CompletableFuture class in Java is used for managing asynchronous tasks. In this class, the runAsync and supplyAsync methods are used in different scenarios.

What Are the Differences?

  • The runAsync method accepts a Runnable task and does not return any value. It is typically used for performing asynchronous operations that cause side effects (e.g., writing to a file, adding records to a database).
  • The supplyAsync method accepts a Supplier task and returns a value. It is used for performing asynchronous computations and returning a result.
  • runAsync requires fewer resources because it only starts a thread.
  • supplyAsync may use more resources because it works with a Future object, which handles both the thread and the result of the task.
CompletableFuture.runAsync(() -> {
// This block works asynchronously
System.out.println("İşlem yapılıyor...");
});
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// Bu blok asenkron olarak çalışır ve bir değer döndürür
return 42;
});

ArrayList vs LinkedList

ArrayList stores data using an array, which provides fast random access. On the other hand, LinkedList uses a doubly linked list, where elements are stored as connected nodes along the list.

What Are the Differences?

  • ArrayList: Suitable for situations that require random access and reading, such as retrieving data from a database.
  • ArrayList: Adding and removing elements takes time (O(n)), so it is not suitable for situations where these operations are frequent.
  • ArrayList: Cache-friendly, as it stores elements consecutively in memory, which improves memory access speed.
  • LinkedList: Suitable for situations that require fast insertion and removal of nodes, such as adding or removing nodes in user interface applications.
  • LinkedList: Inserting or removing nodes at any point is fast (O(1)), making it ideal for these operations.
  • LinkedList: Not cache-friendly, as each node is stored independently in memory, which can reduce memory access speed.

ArrayList is more suitable for data reading scenarios, while LinkedList is better for scenarios where frequent insertion and removal of elements occur.

Shallow Copy vs Deep Copy

Shallow Copy creates a new instance of the original object, but it only copies the references to the objects contained within, not the objects themselves. Primitive data types (e.g., int, boolean, float) are copied directly. The object references are not copied; they continue to point to the same objects as the original.

Deep Copy creates an exact copy of the original object, including copying all objects contained within the original. It copies both the primitive data and the references pointing to objects, effectively duplicating the objects themselves.

What Are the Differences?

  • Shallow Copy: Shares object references. Since only references are copied, it is faster.
  • Shallow Copy: If the original object is modified or its contained objects are changed, it may affect the original object.
  • Deep Copy: Creates entirely new objects and new references. It is more complex because it copies all objects in the object hierarchy.
  • Deep Copy: Since the copy of the original object is independent, changes to it will not affect the original object.

OpenJDK vs Oracle JDK

OpenJDK

OpenJDK (Open Java Development Kit) is an open-source implementation of the Java SE (Standard Edition) platform. It is developed by the community and licensed under the GPL v2 with the Classpath Exception. This license allows free use in commercial projects and is suitable for open-source communities.

Advantages:

  • Completely free.
  • Compatible with Java SE.
  • Continuously developed and tested by the community.

Disadvantages:

  • Does not provide commercial support (separate from Oracle).
  • Updates may sometimes come later than those in Oracle JDK.

Oracle JDK

Oracle JDK is a commercial JDK distribution developed, tested, and optimized by Oracle. Since 2019, Oracle JDK comes under the Oracle Technology Network License (OTN), which is paid for commercial use but free for development, testing, and educational purposes.

Advantages:

  • Optimized performance provided by Oracle.
  • Comprehensive support for commercial applications.
  • Long-Term Support (LTS) releases.

Disadvantages:

  • Paid for commercial use.
  • Limited access to features developed by the open-source community.

Http1 vs Http2

HTTP (Hypertext Transfer Protocol) is a protocol that facilitates communication between the client and the server. HTTP/1.1 and HTTP/2 offer different design approaches to optimize web performance and user experience.

HTTP/1.1

  • A separate HTTP request is sent for each static file (e.g., .css, .js, .png), which increases the number of connections between the client and the server and negatively impacts load times.
  • All messages are transmitted in a text-based format, which, while providing readability, consumes more bandwidth.
  • Header information is sent without compression with each request, which can cause delays, especially when transporting large headers.
  • A single HTTP request receives only one response (1:1 model).

Disadvantages of HTTP/1.1:

  • A new TCP connection may need to be established for each request (if Keep-Alive is not used).
  • Waiting for the completion of one request can delay the responses of other requests.

HTTP/2

HTTP/2 is designed to address the limitations of HTTP/1.1 and enhance the performance of web applications:

  • All requests can be sent and received simultaneously over a single TCP connection, enabling parallel data transmission and reducing latency.
  • HTTP/2 uses a binary format instead of text, making the protocol faster and more efficient. Data is transmitted in smaller chunks, called frames.
  • HTTP/2 compresses header information, which improves performance by preventing the repeated sending of large headers.
  • The server can send resources that need to be preloaded, even before the client requests them. For example, CSS and JS files can be automatically sent along with the HTML document.
  • A single request can return multiple responses (e.g., in the form of different frames).

Advantages of HTTP/2:

  • Multiple requests and responses can be handled over a single TCP connection.
  • Response times are faster due to multiplexing and compression techniques.
  • The priority of requests and responses can be specified.

See you in the next article.

--

--

Didem AĞDOĞAN
Didem AĞDOĞAN

Written by Didem AĞDOĞAN

Software Developer, Traveller, Curious

Responses (1)