Why do 10000 start () call threads take longer than 10,000 run () calls?

I use the hello world for threads, I created a simple thread using the run() call (which is just a normal method call) and a duplicate thread using the start () call, which spawns another thread However, to handle the time spent on start() calls more than for run() calls that are not stream calls, why is this so?

Call start time: 00: 00: 08: 300

  long time = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { Thread thread = new Thread(new Car()); thread.setName(Integer.toString(i)); thread.start(); } long completedIn = System.currentTimeMillis() - time; System.out.println(DurationFormatUtils.formatDuration(completedIn, "HH:mm:ss:SS")); 

Run call time: 00: 00: 01: 366

  long time = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { Thread thread = new Thread(new Car()); thread.setName(Integer.toString(i)); thread.run(); } long completedIn = System.currentTimeMillis() - time; System.out.println(DurationFormatUtils.formatDuration(completedIn, "HH:mm:ss:SS")); 
+6
source share
6 answers

From the commentary to the accepted answer: "Could you advise this?"

Yes, do not use streams directly. Starting with java 5, we have the java.util.concurrent infrastructure, which makes it easier to manage threads and tasks.

Creating a thread is expensive. This is before the thread completes the task you want, it must be created, a very long process. For this reason, we have the concept of a thread pool. Instead of creating new threads every time you want to perform a parallel task, you create the threads you need so that they are ready, and you will send them tasks when you need it. Pool threads as a second adventure. When the task is completed, the thread will not be destroyed, but will be active to run the next task, so the cost of creating a thread occurs only once during initialization.

So how do you use theses?

First create an artist with a thread pool. To stay simple, we create a thread pool with 100 threads (since you want to simulate a load of 100 simultaneous calls):

 ExecutorService pool = Executors.newFixedThreadPool(100); 

Then you submit your tasks:

 long time = System.currentTimeMillis(); for (int i=0; i<100000; i++) { pool.execute(new Car()); } 

And importantly, you will wait until all tasks are completed before the program stops.

 pool.shutdown(); //Do no longer accept new tasks. pool.awaitTermination(1, TimeUnit.HOURS); //Wait for up to one hour for all tasks to finish. long completedIn = System.currentTimeMillis() - time; System.out.println(DurationFormatUtils.formatDuration(completedIn, "HH:mm:ss:SS")); 

In your thread code, you did not wait for the threads to finish working; in fact, you set the thread creation time, not the task execution time.

What does the code do?

The executor.execute method executes the provided task inside the thread. Here it takes one of 100 threads and allows it to complete the task.

What happens if there are more than 100 tasks?

With 100 threads, you cannot run more than 100 simultaneous tasks. Other tasks will be queued until one task is completed so that one thread is available for its execution. This is a good way to make sure that you are not creating too many threads and that OutOfMemory or other unpleasant things are not happening.

How many threads should you use?

It depends on the type of tasks you want to complete.

If this looks like a web server, you are usually tied to IO, waiting for the database to receive data, and then for the network to send a response, your stream will basically wait. Thus, even one processor will benefit from a dozen, even a hundred threads. And even if more threads begin to slow down the entire application, it allows you to process a user’s request instead of making it wait or simply refuse a response.

If your task is CPU related, you need something like one task per CPU core to make the most of your hardware, but limit the overhead to context switches. With a 4-core hyper-thread processor, you can go up to 8 simultaneous threads.

This answer is just a brief introduction ... You will find out more by looking at the java.util.concurrent package and read some tutorials.

+6
source

start actually creates a new thread (heavy operation), and run calls the run method of the thread object on the current thread (a simple method call is the work of light)

In Thread docs regarding start :

Causes this thread to begin execution; Java Virtual Machine calls to start this thread. As a result, two threads are executed simultaneously: the current thread (which returns from the call to the start method), and the other thread (which executes its launch method).

+6
source

You should never call run directly. What you did there creates a bunch of Thread objects, but you never create new threads; you just run the code in the main thread (because you call run directly).

Creating 100,000 threads will not work well on most modern computers (I am leaving high-performance multi-million dollar machines). As soon as you have more threads than you have processor support, you start invoking context switches. Therefore, if you have a quad-core system, starting more than four threads will actually slow down your program (I / O operations with the module, etc., when the CPU will idle anyway).

+3
source

When you start a bunch of threads, and you only have one or two cores, the time it takes to switch context and complete tasks can easily exceed the time it takes to run the code sequentially, one task after another.

+1
source

The start method is magic. This spawns a new thread that takes time:

  • create stream
  • start flow
  • manage the flow life cycle

A better explanation will be found in java.lang.Thread sources.

+1
source

The start method is to start the stream, but it is a simple Runnable interface method.

The Thread.start () method will create a new thread (executable, real) that will execute the run () method of your thread instance.

The run () method can be called on a thread instance, because there are two ways to determine if a thread will execute.

  • Old: extension to the thread start method. It is not recommended to use this for some reason, including communication.

  • New: Passing Runnable (which provides the run () method) to the thread constructor.

Please note: if you create a thread with Runnable (target) and also override the run () method of the thread, you can understand that you are currently executing 2 codes to execute, but which one will be executed? This is easy to find if you look at the default implementation of run () for a thread:

 public void run() { if (target != null) { target.run(); } } 

If you override this method, the provided Runnable target will be bypassed unless you name it when overriding.

As I said, there are two ways to start a thread. I assume that when they developed the β€œnew way”, they had to save this run () method in the Thread class for compatibility issues, but if they could go back in time, they probably wouldn't force the Thread class to implement the Runnable interface , there will be less confusion as to how threads should be started ...

+1
source

Source: https://habr.com/ru/post/893441/


All Articles