Thread or Runnable or Lambda ?

Joe

Thành viên VIP
21/1/13
3,007
1,335
113
“Should I implement a Runnable or extend the Thread class”? is quite a common question.
In this article, we'll see which approach makes more sense in practice and why.
(more: click HERE)
And people pilgrimaged to Stackoverflow.com and asked for the "advantages/disadvantages" between Thread and Runnable (up Java 8: lambda): HERE or some gurus tried to explain us what Thread and Runnable are (click HERE or HERE). Whatever the gurus talk about I still miss the most important aspect about Thread and Runnable (or Lambda). It's about the processing aspect. Single Inheritance or leeway with Interfaces are more or less the discussion theme of the gurus and the asking people seem to ignore the structural and functional aspects about Thread and Runnable. In essence, the gurus favor Runnable because Runnable Interface allows developers to run it as an "OWN" Thread and NOT as a "PSEUDO" Thread by Extension. Let study the implementations:
Thread:
Java:
public class IsThread extends Thread {
  public static void main(String[] args) throws Exception {
    (new IsThread()).start();
  }
  public IsThread() { }
  public void run() {
    System.out.println("I'm a THREAD");
  }
}
Runnable
Java:
public class IsRunnable implements Runnable {
  public static void main(String[] args) throws Exception {
    (new Thread(new IsRunnable())).start();
  }
  public IsRunnable() { }
  public void run() {
    System.out.println("I'm a Runnable");
  }
}
Lambda
Java:
public class IsLambda {
  public static void main(String[] args) throws Exception {
    (new Thread(()->{
        System.out.println("I'm a Lambda");
     })).start();
  }
}
From the three implementations it's easy to miss the most important point that Thread-Extension is itself a SINGLE object which can be ONCE loaded, initialized and executed, while Runnable or Lambda object NEEDs a Thread as a vehicle for its execution. Meaning: First, the Runnable is loaded, initialized, then a THREAD is created, loaded, initialized with the Runnable before the thread is executed on behalf of the Runnable.

Structurally Runnable object always requires an additionally Thread object and that causes naturally more overheads than a Thread extension.

Functionally Runnable takes more time (and resources) than a Thread extension. And that means that some performance impacts by Runnable.

Lambda Expression always looks more superb and advanced than Runnable. For the developers Lambda expression shortens the writing work and saves them from name-finding. Fine, isn't it? BUT: "Nothing comes from nothing." says a proverb. Beside the mentioned disadvantages of Runnable the (hidden from the users) implementation of Lambda causes the most code-overhead. And again: "Nothing comes from nothing." More codes = more work = slower.

Let's check the implementations with a POOL (concurrency):
Thread:
Java:
public class PoolThread extends Thread {
  public static void main(String[] args) throws Exception {
    java.util.concurrent.ForkJoinPool pool = java.util.concurrent.ForkJoinPool.commonPool();
    pool.execute((new PoolThread()));
    pool.awaitTermination(1, java.util.concurrent.TimeUnit.MILLISECONDS);
  }
  public PoolThread() { }
  public void run() {
    System.out.println("I'm a POOLTHREAD");
  }
}
Runnable
Java:
public class PoolRunnable implements Runnable {
  public static void main(String[] args) throws Exception {
    java.util.concurrent.ForkJoinPool pool = java.util.concurrent.ForkJoinPool.commonPool();
    pool.execute(new PoolRunnable());
    pool.awaitTermination(1, java.util.concurrent.TimeUnit.MILLISECONDS);
  }
  public PoolRunnable() { }
  public void run() {
    System.out.println("I'm a PoolRunnable");
  }
}
Lambda
Java:
public class PoolLambda {
  public static void main(String[] args) throws Exception {
    java.util.concurrent.ForkJoinPool pool = java.util.concurrent.ForkJoinPool.commonPool();
    pool.execute(()->{
        System.out.println("I'm a PoolLambda");
     });
    pool.awaitTermination(1, java.util.concurrent.TimeUnit.MILLISECONDS);
  }
}
You may note the expression "pool.awaitTermination(1, java.util.concurrent.TimeUnit.MILLISECONDS);" This expression tries to tell the users that the start of execution could still be dragged on when the app has already terminated. Or in other words: without this expression the app could end without producing any printout. Because Thread (or task) execution time depends on the local Operating System (OS) PURE JAVA implementation can do nothing for the scheduling of the threads (or tasks) in a fixed timing schema. And that causes a lot of headaches for those who lack the understanding of Computer Science (CS) or IT in general. The question HERE of a member of CDJ confirms the nature of the arbitrary execution of Threads (or Tasks or Jobs, if you so will).

Some screenshots:
ThreadRunnableLambda.jpg

The sizes:
ThreadRunnableLambdaSize.jpg

and with POOL
ThreadRunnableLambdaPoolSize.jpg
 
Sửa lần cuối: