📜  Java中的 ThreadFactory 接口与示例

📅  最后修改于: 2022-05-13 01:55:38.081000             🧑  作者: Mango

Java中的 ThreadFactory 接口与示例

Java.util.concurrent包中定义的ThreadFactory接口基于工厂设计模式。顾名思义,它用于按需创建新线程。线程可以通过两种方式创建:

1. 创建一个扩展Thread类的类,然后创建它的对象。

Java
import java.io.*;
 
class GFG {
   
    public static void main(String[] args)
    {
        // Creating a thread
        Thread thread = new CustomThread();
        thread.start(); // Starting execution of the created
                        // thread
    }
}
 
// Creating a class that extends the Thread class
class CustomThread extends Thread {
    @Override public void run()
    {
        System.out.println("This is a thread");
    }
}


Java
/*package whatever //do not write package name here */
 
import java.io.*;
 
class GFG {
    public static void main(String[] args)
    {
        // Creating a Runnable object
        Runnable task = new Task();
        // Creating a thread using the Runnable object
        Thread thread = new Thread(task);
        // Starting the execution of the created thread
        thread.start();
    }
}
 
class Task implements Runnable {
    @Override public void run()
    {
        System.out.println("This is a thread");
    }
}


Java
import java.util.concurrent.ThreadFactory;
import java.io.*;
 
class CustomThreadFactory implements ThreadFactory {
 
    // newThread is a factory method
    // provided by ThreadFactory
    public Thread newThread(Runnable command)
    {
        return new Thread(command);
    }
}


Java
// Java code to demonstrate ThreadFactory interface
 
import java.util.concurrent.ThreadFactory;
import java.io.*;
import java.util.ArrayList;
 
class ThreadFactoryExample {
    public static void main(String[] args)
    {
        // Creating a CustomThreadFactory object
        CustomThreadFactory threadFactory
            = new CustomThreadFactory();
 
        // Creating Runnable objects using the lambda
        // expression
        Runnable command1 = ()
            -> System.out.println("Command 1 executed");
        Runnable command2 = ()
            -> System.out.println("Command 2 executed");
        Runnable command3 = ()
            -> System.out.println("Command 3 executed");
        Runnable command4 = ()
            -> System.out.println("Command 4 executed");
        Runnable command5 = ()
            -> System.out.println("Command 5 executed");
 
        // Putting the commands in an ArrayList
        ArrayList array = new ArrayList<>(5);
        array.add(command1);
        array.add(command2);
        array.add(command3);
        array.add(command4);
        array.add(command5);
 
        // creating threads and running them
        for (Runnable command : array) {
            threadFactory.newThread(command).start();
        }
 
        // print the thread count
        System.out.println(
            "Total number of threads created using CustomThreadFactory = "
            + threadFactory.getCount());
    }
}
 
// ThreadFactory class
class CustomThreadFactory implements ThreadFactory {
 
    // stores the thread count
    private int count = 0;
 
    // returns the thread count
    public int getCount() { return count; }
 
    // Factory method
    @Override
      public Thread newThread(Runnable command)
    {
        count++;
        return new Thread(command);
    }
}


Java
// Java program to demonstrate default
// ThreadFactory
 
import java.io.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
 
class DefaultThreadFactoryExample {
    public static void main(String[] args)
    {
        // Default ThreadFactory
        ThreadFactory threadFactory
            = Executors.defaultThreadFactory();
 
        for (int i = 1; i < 10; i++) {
 
            // Creating new threads with the default
            // ThreadFactory
            Thread thread
                = threadFactory.newThread(new Command());
 
            // print the thread names
            System.out.println(
                "Name given by threadFactory = "
                + thread.getName());
 
            // run the thread
            thread.start();
        }
    }
}
 
class Command implements Runnable {
 
    @Override public void run()
    {
        // Run some code
    }
}


Java
// Java program to demonstrate ThreadFactory
// using default implementation
 
import java.io.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
 
class DefaultThreadFactoryExample {
    public static void main(String[] args)
    {
 
        for (int i = 1; i < 10; i++) {
 
            // Default ThreadFactory
            ThreadFactory threadFactory
                = Executors.defaultThreadFactory();
 
            // Creating new threads with the default
            // ThreadFactory
            Thread thread
                = threadFactory.newThread(new Command());
 
            // print the thread name
            System.out.println(
                "Name given by threadFactory = "
                + thread.getName());
 
            // start the thread
            thread.start();
        }
    }
}
 
class Command implements Runnable {
    @Override public void run()
    {
        // Run some code
    }
}



输出
This is a thread

2. 创建一个实现 Runnable 接口的类,然后使用它的对象创建线程。

Java

/*package whatever //do not write package name here */
 
import java.io.*;
 
class GFG {
    public static void main(String[] args)
    {
        // Creating a Runnable object
        Runnable task = new Task();
        // Creating a thread using the Runnable object
        Thread thread = new Thread(task);
        // Starting the execution of the created thread
        thread.start();
    }
}
 
class Task implements Runnable {
    @Override public void run()
    {
        System.out.println("This is a thread");
    }
}


输出
This is a thread

但是, ThreadFactory是创建新线程的另一种选择。该接口提供了一个工厂方法,该方法在调用时创建并返回新线程。这个工厂方法将一个 Runnable 对象作为参数并使用它创建一个新线程。

ThreadFactory 的层次结构

java.util.concurrent
    ↳ Interface ThreadFactory

ThreadFactory 接口的实现

由于 ThreadFactory 是一个接口,因此必须首先实现其中定义的工厂方法才能使用。这是 ThreadFactory 接口的最简单实现:

Java

import java.util.concurrent.ThreadFactory;
import java.io.*;
 
class CustomThreadFactory implements ThreadFactory {
 
    // newThread is a factory method
    // provided by ThreadFactory
    public Thread newThread(Runnable command)
    {
        return new Thread(command);
    }
}

现在,我们可以创建CustomThreadFactory类的对象并使用其 newThread(Runnable command) 方法按需创建新线程。在上面的实现中,newThread 方法只是通过调用以 Runnable 命令为参数的 Thread 构造函数来创建一个新线程。

有许多类(例如 ScheduledThreadPoolExecutor 、 ThreadPoolExecutor等)使用线程工厂在需要时创建新线程。这些类具有接受 ThreadFactory 作为参数的构造函数。如果未给出任何自定义 ThreadFactory,则它们使用 ThreadFactory 接口的默认实现。

Java.util.concurrent 包中的Executors类提供了Executors.defaultThreadFactory()静态方法,该方法返回 ThreadFactory 接口的默认实现。

示例:下面的示例代码演示了 ThreadFactory 接口。

Java

// Java code to demonstrate ThreadFactory interface
 
import java.util.concurrent.ThreadFactory;
import java.io.*;
import java.util.ArrayList;
 
class ThreadFactoryExample {
    public static void main(String[] args)
    {
        // Creating a CustomThreadFactory object
        CustomThreadFactory threadFactory
            = new CustomThreadFactory();
 
        // Creating Runnable objects using the lambda
        // expression
        Runnable command1 = ()
            -> System.out.println("Command 1 executed");
        Runnable command2 = ()
            -> System.out.println("Command 2 executed");
        Runnable command3 = ()
            -> System.out.println("Command 3 executed");
        Runnable command4 = ()
            -> System.out.println("Command 4 executed");
        Runnable command5 = ()
            -> System.out.println("Command 5 executed");
 
        // Putting the commands in an ArrayList
        ArrayList array = new ArrayList<>(5);
        array.add(command1);
        array.add(command2);
        array.add(command3);
        array.add(command4);
        array.add(command5);
 
        // creating threads and running them
        for (Runnable command : array) {
            threadFactory.newThread(command).start();
        }
 
        // print the thread count
        System.out.println(
            "Total number of threads created using CustomThreadFactory = "
            + threadFactory.getCount());
    }
}
 
// ThreadFactory class
class CustomThreadFactory implements ThreadFactory {
 
    // stores the thread count
    private int count = 0;
 
    // returns the thread count
    public int getCount() { return count; }
 
    // Factory method
    @Override
      public Thread newThread(Runnable command)
    {
        count++;
        return new Thread(command);
    }
}


输出
Command 1 executed
Command 2 executed
Command 4 executed
Command 3 executed
Command 5 executed
Total number of threads created using CustomThreadFactory = 5

为什么要使用线程工厂?

在上面的示例中, newThread(Runnable)工厂方法最终使用给定的 Runnable 命令创建了一个新线程。那为什么要使用ThreadFactory呢?我们可以通过调用我们在 newThread(Runnable) 方法中所做的 Thread 构造函数,直接从 Runnable 命令创建线程。这里有一些原因,

  • 我们可以给线程更有意义的自定义名称。它有助于分析它们的目的以及它们的工作方式。
  • 我们可以获取有关创建线程的统计信息,例如线程数和其他详细信息。我们可以根据统计信息限制新线程的创建。
  • 我们可以设置线程的守护进程状态。
  • 我们可以设置线程优先级。
  • 我们可以将所有功能限制在一个类中。

默认线程工厂

它是由Executors.defaultThreadFactory()静态方法实现的默认线程工厂。许多类(例如 ScheduledThreadPoolExecutor、 ThreadPoolExecutor等)在未指定任何自定义 ThreadFactory 时使用此默认 ThreadFactory。这些类使用默认的 ThreadFactory 创建新线程。这个默认的 ThreadFactory 在同一个 ThreadGroup 中创建所有新线程(一个 ThreadGroup 代表一组线程)。所有创建的新线程都是非守护进程,优先级设置为 Thread.NORM_PRIORITY 中的最小值和 ThreadGroup 中允许的最大优先级。此默认 ThreadFactory 创建的线程以pool-N-thread-M的形式命名(例如,pool-1-thread-1、pool-1-thread-2、pool-2-thread-1 等。 ) 其中N是这个工厂的序列号, M是这个工厂创建的线程的序列号。

示例:下面的示例演示了如何使用默认的 ThreadFactory。

Java

// Java program to demonstrate default
// ThreadFactory
 
import java.io.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
 
class DefaultThreadFactoryExample {
    public static void main(String[] args)
    {
        // Default ThreadFactory
        ThreadFactory threadFactory
            = Executors.defaultThreadFactory();
 
        for (int i = 1; i < 10; i++) {
 
            // Creating new threads with the default
            // ThreadFactory
            Thread thread
                = threadFactory.newThread(new Command());
 
            // print the thread names
            System.out.println(
                "Name given by threadFactory = "
                + thread.getName());
 
            // run the thread
            thread.start();
        }
    }
}
 
class Command implements Runnable {
 
    @Override public void run()
    {
        // Run some code
    }
}


输出
Name given by threadFactory = pool-1-thread-1
Name given by threadFactory = pool-1-thread-2
Name given by threadFactory = pool-1-thread-3
Name given by threadFactory = pool-1-thread-4
Name given by threadFactory = pool-1-thread-5
Name given by threadFactory = pool-1-thread-6
Name given by threadFactory = pool-1-thread-7
Name given by threadFactory = pool-1-thread-8
Name given by threadFactory = pool-1-thread-9

请注意默认 ThreadFactory 给出的线程名称。它创建了 9 个线程,所有线程都在同一个 ThreadGroup 中。所有线程都是使用相同的 ThreadFactory 创建的(因此线程的名称采用pool -1 -thread-M的形式)。

例子:

Java

// Java program to demonstrate ThreadFactory
// using default implementation
 
import java.io.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
 
class DefaultThreadFactoryExample {
    public static void main(String[] args)
    {
 
        for (int i = 1; i < 10; i++) {
 
            // Default ThreadFactory
            ThreadFactory threadFactory
                = Executors.defaultThreadFactory();
 
            // Creating new threads with the default
            // ThreadFactory
            Thread thread
                = threadFactory.newThread(new Command());
 
            // print the thread name
            System.out.println(
                "Name given by threadFactory = "
                + thread.getName());
 
            // start the thread
            thread.start();
        }
    }
}
 
class Command implements Runnable {
    @Override public void run()
    {
        // Run some code
    }
}


输出
Name given by threadFactory = pool-1-thread-1
Name given by threadFactory = pool-2-thread-1
Name given by threadFactory = pool-3-thread-1
Name given by threadFactory = pool-4-thread-1
Name given by threadFactory = pool-5-thread-1
Name given by threadFactory = pool-6-thread-1
Name given by threadFactory = pool-7-thread-1
Name given by threadFactory = pool-8-thread-1
Name given by threadFactory = pool-9-thread-1

在这里,我们使用了 9 个不同的默认 ThreadFactories(在每个循环中我们都在创建一个新的!)。所以每个线程都在不同的 ThreadGroup 中,因此线程以pool-N-thread-1的形式命名。

默认的 ThreadFactory 实现创建具有正常优先级的非守护线程,并以pool-N-thread-M的形式给出名称,其中不包含有关它们如何工作和做什么的信息。这会在调试和其他重要目的中产生很多问题。然而,这个问题可以使用自定义的 ThreadFactory 来解决,它可以为线程提供更有意义的名称,并可以设置守护进程和优先级状态。

线程工厂的方法

METHOD

DESCRIPTION

newThread​(Runnable r)Constructs a new Thread.