Grouping threads is an interesting feature provided by the Java concurrency API. We can treat a group of threads as an independent unit and can manipulate the thread objects in the thread group at will. For example, you can control a group of threads to run the same task without caring about how many threads are still running, and you can also use an interrupt call to interrupt the execution of all threads.
Java provides the ThreadGroup class to control a thread group. A thread group can be created through a thread object, or it can be created by other thread groups to generate a tree structure of threads.
According to "Effective Java", the use of ThreadGroup is no longer recommended. It is recommended to use Executor.
——D Guagot explains this.
In this section, we use ThreadGroup to develop a simple example. We will create ten threads with varying sleep times (like simulating a search) and when one of them completes, interrupt the rest.
know it
Follow the steps shown below to complete the sample code.
1. Create a class named Result to store the name of the first thread to complete the task. Declare a private variable of type String, name, and generate Setter/Getter methods. The code is as follows:
Copy the code code as follows:
public class Result {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2. Create a class named SearchTask and implement the Runnable interface. The code is as follows:
Copy the code code as follows:
public class SearchTask implements Runnable {
3. Declare a private variable of type Result and instantiate the variable through the constructor. The code is as follows:
Copy the code code as follows:
private Result result;
public SearchTask(Result result) {
this.result = result;
}
4. Implement the run() method and call the doTask() method in it to wait for completion or interruption. This method also prints information to the console to show the thread's start, end, or interruption. The code is as follows:
Copy the code code as follows:
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.printf("Thread %s: Start/n", name);
try {
doTask();
result.setName(name);
} catch (InterruptedException e) {
System.out.printf("Thread %s: Interrupted/n", name);
return;
}
System.out.printf("Thread %s: End/n", name);
}
5. Implement the doTask() method, which will create a Random object and then use the object to generate a random number to adjust the thread sleep time. The code is as follows:
Copy the code code as follows:
// Simulate search
private void doTask() throws InterruptedException {
Random random = new Random(new Date().getTime());
int value = (int) (random.nextDouble() * 100);
System.out.printf("Thread %s: %d/n",
Thread.currentThread().getName(), value);
TimeUnit.SECONDS.sleep(value);
}
6. Create the main class of the sample program, Main, and implement the main() method. The code is as follows:
Copy the code code as follows:
public class Main {
public static void main(String[] args) {
7. Create a ThreadGroup object named Searcher. The code is as follows:
Copy the code code as follows:
ThreadGroup threadGroup = new ThreadGroup("Searcher");
8. Then, create a Result object and SearchTask object. The code is as follows:
Copy the code code as follows:
Result result = new Result();
SearchTask searchTask = new SearchTask(result);
9. Use the SearchTask object to create ten Thread objects, and when creating a Thread object, pass the ThreadGroup object as the first parameter to the constructor of the Thread class. The code is as follows:
Copy the code code as follows:
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(threadGroup, searchTask);
thread.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
10. Use the list() method to print out the information of the ThreadGroup object. The code is as follows:
Copy the code code as follows:
System.out.printf("Number of Threads: %d/n", threadGroup.activeCount());
System.out.println("Information about the Thread Group");
threadGroup.list();
11. Use activeCount() and enumerate() to get the number of active threads in the ThreadGroup object and copy it to a thread array. Use the get*() method to get the name and status of the thread. The code is as follows:
Copy the code code as follows:
Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
for (int i = 0; i < threadGroup.activeCount(); i++) {
System.out.printf("Thread %s: %s/n", threads[i].getName(),
threads[i].getState());
}
12. Call the waitFinish() method and wait for one of the threads in the ThreadGroup object to complete the task. Implement this method later. The code is as follows:
Copy the code code as follows:
waitFinish(threadGroup);
13. Use the interrupt() method to interrupt other threads in the thread group. The code is as follows:
Copy the code code as follows:
threadGroup.interrupt();
14. Implement the waitFinish() method and use the activeCount() method to control the execution results of the thread. The code is as follows:
Copy the code code as follows:
// Wait for task to complete
private static void waitFinish(ThreadGroup threadGroup) {
while (threadGroup.activeCount() > 9) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
15. Run the program and check the execution effect.
know why
Below is the result of program execution. You will see the output of the list() method, the status of each thread, etc.
Copy the code code as follows:
Thread Thread-0: Start
Thread Thread-0: 52
Thread Thread-1: Start
Thread Thread-1: 41
Thread Thread-2: Start
Thread Thread-2: 69
Thread Thread-3: Start
Thread Thread-3: 60
Thread Thread-4: Start
Thread Thread-4: 88
Number of Threads: 5
Information about the Thread Group
java.lang.ThreadGroup[name=Searcher,maxpri=10]
Thread[Thread-0,5,Searcher]
Thread[Thread-1,5,Searcher]
Thread[Thread-2,5,Searcher]
Thread[Thread-3,5,Searcher]
Thread[Thread-4,5,Searcher]
Thread Thread-0: TIMED_WAITING
Thread Thread-1: TIMED_WAITING
Thread Thread-2: TIMED_WAITING
Thread Thread-3: TIMED_WAITING
Thread Thread-4: TIMED_WAITING
Thread Thread-1: Interrupted
Thread Thread-4: Interrupted
Thread Thread-2: Interrupted
Thread Thread-0: Interrupted
Thread Thread-3: Interrupted
The ThreadGroup class stores many Thread objects and associated ThreadGroup objects. You can access thread information by calling methods of this class, and you can also perform various operations on it, such as interrupts.
never ending
The ThreadGroup class also has many methods. Please read the API documentation for complete method descriptions.
Use doctrine
This article is translated from "Java 7 Concurrency Cookbook" (D Gua Ge stole it as "Java7 Concurrency Example Collection") and is only used as learning materials. It may not be used for any commercial purposes without authorization.
Small success
Below is the complete version of the code used in the examples in this section.
Complete code of Result class:
Copy the code code as follows:
package com.diguage.books.concurrencycookbook.chapter1.recipe10;
/**
* Store query results
* Date: 2013-09-30
* Time: 00:45
*/
public class Result {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The complete code of the SearchTask class is as follows:
package com.diguage.books.concurrencycookbook.chapter1.recipe10;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* Simulation search class
* Date: 2013-10-02
* Time: 22:38
*/
public class SearchTask implements Runnable {
private Result result;
public SearchTask(Result result) {
this.result = result;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.printf("Thread %s: Start/n", name);
try {
doTask();
result.setName(name);
} catch (InterruptedException e) {
System.out.printf("Thread %s: Interrupted/n", name);
return;
}
System.out.printf("Thread %s: End/n", name);
}
// Simulate search
private void doTask() throws InterruptedException {
Random random = new Random(new Date().getTime());
int value = (int) (random.nextDouble() * 100);
System.out.printf("Thread %s: %d/n",
Thread.currentThread().getName(), value);
TimeUnit.SECONDS.sleep(value);
}
}
The complete code of the Main class:
Copy the code code as follows:
package com.diguage.books.concurrencycookbook.chapter1.recipe10;
import java.util.concurrent.TimeUnit;
/**
* Thread group example main class
* Date: 2013-10-02
* Time: 22:45
*/
public class Main {
public static void main(String[] args) {
ThreadGroup threadGroup = new ThreadGroup("Searcher");
Result result = new Result();
SearchTask searchTask = new SearchTask(result);
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(threadGroup, searchTask);
thread.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Number of Threads: %d/n", threadGroup.activeCount());
System.out.println("Information about the Thread Group");
threadGroup.list();
Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
for (int i = 0; i < threadGroup.activeCount(); i++) {
System.out.printf("Thread %s: %s/n", threads[i].getName(),
threads[i].getState());
}
waitFinish(threadGroup);
threadGroup.interrupt();
}
// Wait for task to complete
private static void waitFinish(ThreadGroup threadGroup) {
while (threadGroup.activeCount() > 9) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}