Thread Creation and Attributes
ID and Name
Every thread has an id and a name. The id is an incrementing integer; it increases by one each time a new thread is created. The default value for the name is Thread-[number], which can be specified in the Thread constructor or set using the setName() method.
Priority
Threads have priority levels. In Java, priorities range from 1 to 10, with a default of 5. This priority level maps to the operating system's thread priority; however, different operating systems vary (e.g., some do not support ten distinct priority levels). Different priority levels in Java might map to the same priority level on an operating system. Furthermore, for the operating system, priority serves primarily as a suggestion or hint rather than a mandate. Therefore, one should not rely too heavily on priorities when programming.
Methods to set thread priority in Java: public final void setPriority(int priority).
Method to get thread priority in Java: public final int getPriority().
State
The lifecycle of a thread consists of five states: New (新建), Runnable (就绪), Running (运行), Blocked (阻塞), and Dead (死亡). During the operation of the system, new threads are constantly created while old ones are cleaned up after execution. Threads may be blocked when queuing to acquire shared resources or locks; consequently, running threads switch back and forth between the Runnable, Blocked, and Running states.
Thread Creation
Inheriting the Thread Class
The Thread class implements the Runnable interface and defines methods for operating on threads. We can create a thread by inheriting from the Thread class. The specific implementation involves creating a class that extends the Thread interface, instantiating a thread object, and calling the start() method to launch it. The start() method is a native method; it launches a new thread on the operating system and ultimately executes the run() method to start the thread. The code within the run() method constitutes the specific implementation logic of the thread class. A concrete implementation is provided below:
//step 1:Create NewThread by extending Thread class
public class NewThread extends Thread{
public void run(){
System.out.println("create a thread by extends Thread");
}
}
//step 2:Instantiate a NewThread object
NewThread newThread=new NewThread();
//step 3:Call the start method to launch the NewThread
newThread.start();
The code above defines a thread class named NewThread, which inherits from Thread. The logic within the run() method represents the specific execution behavior of the thread. To use this thread, one simply needs to instantiate an object of this class and call its start() method.
Implementing Runnable Interface
Based on Java language specifications, if a subclass has already inherited another class, it cannot directly inherit from the Thread class anymore; in such cases, threads can be created by implementing the Runnable interface. The specific implementation process involves: creating a thread (ChildrenClass) that implements the Runnable interface, instantiating an object named childrenThread, creating an instance of the Thread class and passing the childrenThread instance to it, and calling the thread's start() method to launch the thread. A concrete implementation is provided below:
//step 1:Create ChildrenClassThread by implementing Runnable interface
public class ChildrenClassThread extends SuperClass implements Runnable{
public void run(){
System.out.printIn("create a thread by implements Runnable");
}
}
//step 2:Instantiate a ChildrenClassThread object
ChildrenClassThread childrenThread= new ChildrenClassThread();
//step 3:Create a Thread instance and pass the instantiated childrenThread to it
Thread thread = new Thread(childrenThread);
//step4:Call the start method to launch a thread
thread.start ();
In fact, after passing an instance of Runnable (target) to the Thread, when the run() method executes within that Thread, it calls the target's run() method and executes the specific implementation logic of that thread. The implementation code for the run() method in JDK source is as follows:
@override
public void run(){
if(target!= null){
target.run();
}
}
Implementing Callable Interface, Overriding call() Method
Sometimes, we need to start multiple threads concurrently from the main thread to execute a task and then collect results returned by each thread before summarizing them. This requires using the Callable interface. The specific implementation method involves: creating a class that implements the Callable interface, implementing the operational logic in the call() method, and returning the calculated result. The calling process consists of: creating an executor service (thread pool), a list to store return results (Future List), and instances of threads using Callable. Tasks are submitted via the thread pool, with execution results saved into Future objects after completion. Once all threads finish executing, iterate through the Future objects in the list; calling the get() method on each object retrieves data returned by the callable task to summarize the result. The implementation code is as follows:
//step 1:Create MyCallable thread by implementing Callable interface
public class MyCallable implements Callable<String>(
private String name;
public MyCallable(String name){//Pass parameters through constructor to define thread name
this.name = name;
}
@Override
public string call() throws Exception{//Implement logic in the call method for the thread
return name;
}
}
//step 2:Create a fixed-size thread pool of size 5
ExecutorService pool= Executors.newFixedThreadPool(5);
//step 3:Create multiple task lists with return values named 'list'
List<Future> list = new ArrayList<Future>();
for(int i= 0;i<5;i++){
//step 4:Create a thread instance that returns a value
Callable c=new MyCallable(i+"");
//step 5:Submit the thread, get the Future object and save it to the Future List
Future future = pool.submit(c);
System.out.println("submit a callable thread:" +i);
list.add(future);
}
//step 6:Shutdown the thread pool and wait for threads to finish execution
pool.shutdown();
//step 7:Iterate through all running results of threads
for(Future future:list){
//Retrieve task return value from Future object and output result to console
System.out.println("get the result from callable thread:"+future.get().toString());
}