Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
JAVA creates threads in three ways
The way JAVA creates threads
In Order to have asynchronous computation in JAVA, we need to start threads to help later computation and run in the background. There are three ways to start threads in JAVA:
- Thread class inheritance
- Implement the Runnable interface
- Use Callable and Future
Similarities and differences in the way threads are created
- Inheriting the Thread class: (1) creating a Thread through the Thread constructor (2) starting a Thread with only one execution per Thread (3) calling this. If you want to share a variable between two threads, you need to declare it as static. Static is not recommended because asynchronous problems can be difficult to control.
- (1) Threads only implement the Runnable interface. They can also inherit other classes and implement other interfaces. (2) Multiple threads can share the same target object (Runnable), which is very suitable for multiple threads processing the same resource; This is a bit tricky to understand, but the following code example will make sense. Thread.currentthread () ¶
- The Callable interface is an enhanced version of the Runnable interface. (2) The Call () method in the Callable interface can either return a value or declare an exception to be thrown
Thread subclasses are created to represent Thread objects. The Runnable object that implements the creation of the Runnable interface can only be used as the target of a thread object. This is why Runnable can share data.
The relationship between FutureTask, Callable, and Future: It implements the RunnableFuture interface, which in turn inherits from the Runnable and Future interfaces, so FutureTask can be either executed by threads as Runnable or returned by Callable as a Future.
public class FutureTask<V> implements RunnableFuture<V> {
}
Copy the code
Three, practice
3.1 Inheriting Thread
class Test { public static int number = 0; public static void main(String[] args) { TestThread testThread = new TestThread(); testThread.start(); TestThread2 testThread2 = new TestThread2(); testThread2.start(); } public static class TestThread extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 10; i++) { System.out.println(this.getName() + ":" + ++number); } } } public static class TestThread2 extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 10; i++) { System.out.println(this.getName() + ":" + ++number); }}}}Copy the code
3.2 Implementing the Runnable Interface
In this code example, two threads share a Runnable, where the Runnable data is shared between the two threads.
class Test { public static void main(String[] args) { TestRunnable testRunnable = new TestRunnable(); New Thread(testRunnable).start(); new Thread(testRunnable).start(); } public static class TestRunnable implements Runnable { int number = 0; @Override public void run() { ++number; System.out.println(Thread.currentThread().getName() + " " + number); }}}Copy the code
3.3 FutureTask: Use Callable and Future
class Test { public static void main(String[] args) { FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>) () -> { int i = 0; while (i < 10) { ++i; } // The call() method returns the value of return I; }); New Thread(task, "Thread with return value ").start(); Try {system.out.println ("task.get() : "+ task.get()); } catch (Exception e) { e.printStackTrace(); }}}Copy the code