如何创建 n 个线程并使用它们

How to create n threads and work with all of them

我正在尝试创建给定数量的线程并同时处理它们以制作“竞赛”程序。线程已创建,但我做错了什么,因为任何线程都打印“Hi”。

public class Principal implements Runnable{

    public static void main(String[] args) {

        int howManyThreads = 3;
        Thread thread[];

        thread = new Thread[howManyThreads];

        for ( int i=0; i < thread.length; i++ ){

            thread[i]= new Thread();
            thread[i].setName("Thread - " + i);
        }

        for ( int i=0; i < thread.length; ++i){

            thread[i].start();
            System.out.println(thread[i].getName() + " - " + thread[i].getState());
        }

    }

    public void run() {

        System.out.println("Hi");
    }
}

Thread class 的默认构造函数创建一个什么也不做的线程。您在这里调用默认构造函数:thread[i] = new Thread();

如果您希望线程实际执行某些操作,则必须提供一个 Runnable 实例作为 Thread 构造函数的参数。有几种方法可以做到这一点。最新、最简洁的方法是使用 lambda 表达式:

thread[i] = new Thread(() -> {
    System.out.println("Hi");
});

Runnable 接口是一个 @FunctionalInterface。由于编译器知道 Thread(...) 构造函数需要该类型的对象,因此它推断这就是 lambda 应该创建的对象,并且 lambda 的主体成为新对象的 run() 方法。


另一种提供 Runnable 对象的旧方法是使用 匿名内部 class 表达式。语法有点麻烦,因为你必须明确地说出新的 class 应该实现什么接口,并且你必须明确声明 run() 方法:

thread[i] = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hi");
    }
});

最古老的方法,甚至更冗长,是显式声明一个命名的 class:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Hi");
    }
};

public class Principal /*does not need to implement Runnable*/ {
    ...
    thread[i] = new Thread(new MyRunnable());
    ...
}

您可能会问,为什么我要从 Principal class 中删除 implements Runnable,然后创建一个全新的 class?

我这样做是因为,我读过这本书:https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/