The last section covered the basics of threads and processes, but for Java, you’ll probably spend more time talking about threads, so the next series of articles will focus on threads.

Create a thread

How to create a thread is a cliched topic and one of the most popular questions to ask in interviews. There is a lot of talk on the Internet about whether implementing a Runnable interface is the same type as implementing a Callable interface. This is not wrong, it just depends on which perspective you look at it from. But there is no need to pay too much attention to such details.

Implement the Runnable interface

Implement the Runnable interface, and then override the run() method, which defines how and what threads work.

public class ImplementsRunnable implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "------Runnable Thread working..." ); } public static void main(String[] args) { for (int i = 0; i < 50; i++) { new Thread(new ImplementsRunnable()).start(); }}}

In the main method, we start 50 threads. To start a Thread, we create a new Thread and pass in the class that implements the Runnable interface. Now let’s look at the results

It can be seen that although we create new threads in order, the execution order of threads is controlled by the CPU, which can be said to be uncontrollable. It is just this that can show that multi-threads are running.

Implement the Callable interface

What needs to be overridden once the interface is implemented is the call() method

public class ImplementsCallable implements Callable { @Override public Object call() { System.out.println(Thread.currentThread().getName() + "-------- Callable working "); Return "implement callable, return value "; } public static void main(String[] args) throws ExecutionException, InterruptedException { for (int i = 0; i < 50; i++) { ImplementsCallable callable = new ImplementsCallable(); FutureTask<String> task = new FutureTask<String>(callable); new Thread(task).start(); System.out.println(task.get()); }}}

It’s worth noting that in the constructor of the Thread class, there are no overloaded constructors with Callable arguments. It’s basically Runnable

With the help of FutureTask class is a more important class in the working principle of threading, which may be a special article to learn in the Future. FutureTask implements the RunnableFuture interface, which in turn inherits Runnable and Future.

The biggest difference with the implementation of Runnable interface is that Callable interface has a return value. What is the scenario in which this return value is used? For example, in an HTTP call, a result needs to be returned. How do we get the return value, using the get() method in FutureTask, and let’s see the result

There is an interesting problem here. When I comment line 14 and run it, I get the following result: the thread is unorganized, which is exactly what I expect.

However, when I keep line 14 to run for many times, the following results will appear again. The thread unexpectedly becomes orderly. If anyone knows why, can you leave a message

Thread class inheritance

After inheriting the Thread class, IDEA doesn’t even remind us that we need to override the run() method manually

The overall code is as follows

public class ExtendsThread extends Thread{ @Override public void run() { System.out.println(Thread.currentThread().getName() + "-------- inherits Thread work "); } public static void main(String[] args) { for (int i = 0; i < 50; i++) { new ExtendsThread().start(); }}}

The code is relatively simple, so let’s look at the result, which is the same as expected

Both methods give priority to implementing interfaces, because Java does not support multiple inheritance. If you inherit Thread class, you cannot inherit from other classes, but you can implement multiple interfaces. Also, inheriting the entire Thread class is cumbersome in terms of performance overhead.

Common Threading Methods

Thread related methods have a variety of more, here to focus on the next 4 commonly used methods.

start

In the above example, we can see that each time we start a thread, we basically use the start() method. What is the difference between the run() method and the start() method

public class CommonMethod { public static void main(String[] args) throws InterruptedException { startRunExample(); } //start,run public static void startRunExample() { new MyThread().start(); new MyThread().run(); } } class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName() + " is running"); }}

Create a new class, then create an inner class that inherits Thread, call the start() and run() methods, and then call the wrapped method inside the main function. See what happens.

You can see that one thread name is the main thread and one is a child thread, so the start() method starts a thread that then executes the contents of the run() method. But if you use the run() method directly, the main thread simply executes the contents of the run() method without starting a new thread.

sleep

When the current thread sleeps, the CPU is freed for other threads to execute.

public class CommonMethod { public static void main(String[] args) throws InterruptedException { // startRunExample(); sleepExample(); // yieldExample(); // waitExample(); // Sleep public static void sleepExample() throws InterruptedException {new MyThread().start(); // Sleep public static void sleepExample() throws InterruptedException {new MyThread().start(); Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + " is running"); } } class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName() + " is running"); }}

For example, if I start a new Thread, but I let the main Thread sleep for 3 seconds before running, the result should be “Thread-0 is running” and then “Main is running” after 3 seconds.

To make a comparison, I’ll comment out the sleep code and look at the results a few more times

You can see that the results of the two threads come out almost at the same time, and which is the first and which is the last is out of our control in this case.

yield

Yield is when the programmer tells the computer to yield the CPU used by the current thread to another thread. However, this is a different matter. In general, this means switching a thread from Running to a Runnable state.

Again, the computer is advised to suspend the current thread and execute other threads, but it is the computer’s business to do so or not.

Create a new inner class YieldThread again

public class CommonMethod { public static void main(String[] args) throws InterruptedException { // startRunExample(); // sleepExample(); yieldExample(); // waitExample(); Yield public static void yieldExample() throws InterruptedException {yieldThread; yield public static void yieldExample() throws InterruptedException {yieldThread () yieldThread = new YieldThread(); Thread thread = new Thread(yieldThread, "thread1"); Thread thread1 = new Thread(yieldThread, "thread2"); thread.start(); thread1.start(); } } class YieldThread extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is running " + i); if (Thread.currentThread().getName().equals("thread1")) { Thread.yield(); } System.out.println(Thread.currentThread().getName() + " yield " + i); }}}

The logic of a run is that each thread runs 10 times, producing a running and a yield each time. But when we add Thread.yield(), the expected result is

thread1 is running
thread2 is running
thread2 yield
thread1 yield

Thread1 executes the running statement, hands over the CPU’s right to use it, and then executes the CPU’s right to execute Thread2, and then obtains the CPU’s time slice to execute the Thread1 yield statement

And then let’s see if it works as expected

You can see that only part of the result works as expected when we remove the Thread.yield() line

Yes, you’ll find this happening occasionally, but not as often as it does above. Because the two threads are likely to be running in parallel, rather than concurrently (running alternately), they execute the running statement at the same time, then thread 2 yields, and thread 1 yields.

To speak here
Not necessarily accurate, so it is not quite accurate example, if there is a better understanding and example can leave a message!!

wait

The following example is a little more controllable than the previous yield, which is a suggestion, and the latter, which can be translated as a force. It converts the thread from Running state to Block state, suspends the thread, and does not execute until it is woken up.

public class CommonMethod { public static void main(String[] args) throws InterruptedException { // startRunExample(); // sleepExample(); // yieldExample(); waitExample(); } public static void WaitThread() {WaitThread = new WaitThread();} public static void WaitThread(); Thread thread1 = new Thread(waitThread, "thread1"); Thread thread2 = new Thread(waitThread, "thread2"); thread1.start(); thread2.start(); } } class WaitThread extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is running " + i); if (Thread.currentThread().getName().equals("thread1")) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }

Thread.yield() instead of wait(). Normally, a Thread named thread1 executes only once and then never executes again

And expected results are the same, and also an error Java lang. IllegalMonitorStateException.

It is not easy to create, if you have help, welcome thumb up, collection and share!

The following is a personal public number, interested can pay attention to, perhaps is your treasure public number oh, basic 2,3 days 1 more technical articles!!