Java concurrent programming example of ten: thread groups

  • 2020-04-01 03:39:16
  • OfStack

Grouping threads is an interesting feature provided by the Java concurrency API. We can treat a group of threads as a separate unit and manipulate the thread objects in the group at will. For example, you can control a set of threads to run the same task without caring how many threads are still running, and you can interrupt the execution of all threads with a single interrupt call.

Java provides a ThreadGroup class to control a group of threads. A thread group can be created by a thread object or by another thread group, generating a tree of threads.

According to Effective Java, threadgroups are no longer recommended. Executor is recommended.

-- grug hereby states.

In this section, we'll use ThreadGroup to develop a simple example. We will create ten threads with different sleep times (such as a mock search), and when one of them completes, interrupt the rest.

learning

Complete the sample code by following the steps shown below.

1. Create a class called 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:


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:


public class SearchTask implements Runnable {

Declare a private variable of type Result and instantiate it with a constructor. The code is as follows:


private Result result; public SearchTask(Result result) {
    this.result = result;
}

4. Implement the run() method, where the doTask() method is called, to wait for completion or to be interrupted. The method also prints information to the console to show the start, end, or interrupt of the thread. The code is as follows:


@Override
public void run() {
    String name = Thread.currentThread().getName();
    System.out.printf("Thread %s: Startn", name);
    try {
        doTask();
        result.setName(name);
    } catch (InterruptedException e) {
        System.out.printf("Thread %s: Interruptedn", name);
        return;
    }
    System.out.printf("Thread %s: Endn", name);
}

5. Implement the doTask() method, which creates a Random object and then USES the object to generate a Random number to adjust how long the thread sleeps. The code is as follows:


//Mock search
private void doTask() throws InterruptedException {
    Random random = new Random(new Date().getTime());
    int value = (int) (random.nextDouble() * 100);
    System.out.printf("Thread %s: %dn",
            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:


public class Main {
    public static void main(String[] args) {

7. Create a ThreadGroup object with the name Searcher. The code is as follows:


ThreadGroup threadGroup = new ThreadGroup("Searcher");

8. Then, create a Result object and a SearchTask object. The code is as follows:


Result result = new Result();
SearchTask searchTask = new SearchTask(result);

9. The SearchTask object creates ten Thread objects using the ThreadGroup object as the first argument to the constructor of the Thread class. The code is 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 information about the ThreadGroup object. The code is as follows:


System.out.printf("Number of Threads: %dn", 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 into an array of threads. Use the get*() method to get the name and state of the thread. The code is as follows:


Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
for (int i = 0; i < threadGroup.activeCount(); i++) {
    System.out.printf("Thread %s: %sn", 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:


waitFinish(threadGroup);

Interrupt () to interrupt other threads in a thread group. The code is as follows:


threadGroup.interrupt();

Implement the waitFinish() method, using the activeCount() method to control the execution of the thread. The code is as follows:


//Wait for the 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 to see how it works.

Know why

Here are the results of the program execution. You'll see the output of the list() method, the state of each thread, and so on.


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 holds numerous Thread objects and the associated ThreadGroup objects. You can call the methods of the class, access the information of the thread, and perform various operations on it, such as interrupts.

endless

The ThreadGroup class also has a number of methods. Consult the API documentation for a complete method description.

si

This article is a translation from the Java7 Concurrency Cookbook (D jago to Java7 Concurrency examples) and is intended for use only as a learning material. Not to be used in any commercial activities without authorization.

Small has becomes

Here is the complete version of the code used in this section of the example.

The complete code of the Result class:


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 for the SearchTask class

package com.diguage.books.concurrencycookbook.chapter1.recipe10; import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit; /**
 * Mock 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: Startn", name);
        try {
            doTask();
            result.setName(name);
        } catch (InterruptedException e) {
            System.out.printf("Thread %s: Interruptedn", name);
            return;
        }
        System.out.printf("Thread %s: Endn", name);
    }     //Mock search
    private void doTask() throws InterruptedException {
        Random random = new Random(new Date().getTime());
        int value = (int) (random.nextDouble() * 100);
        System.out.printf("Thread %s: %dn",
                Thread.currentThread().getName(), value);
        TimeUnit.SECONDS.sleep(value);
    }
}

The complete code of the Main class:


package com.diguage.books.concurrencycookbook.chapter1.recipe10; import java.util.concurrent.TimeUnit; /**
 * Thread group sample 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: %dn", 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: %sn", threads[i].getName(),
                    threads[i].getState());
        }         waitFinish(threadGroup);         threadGroup.interrupt();
    }     //Wait for the task to complete
    private static void waitFinish(ThreadGroup threadGroup) {
        while (threadGroup.activeCount() > 9) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


Related articles: