即使我们在 for 循环中创建一个新线程,如何让所有线程工作?

How to get all the threads working even when we create a new one in the for loop?

执行以下代码,但我希望它打印一个长度与 sample 长度相同的新字符串 tmp

class T10 {
    static String tmp = "", sample = "Manipulate";
    public static void main(String args[]) {
        for(int i=0;i<sample.length();i++)
            new Thread10(i).t.start();
        System.out.println(tmp);
    }
}
class Thread10 implements Runnable {
    int i;
    Thread t;
    Thread10(int i) {
        t = new Thread(this, "Manipulator Thread : "+i);
        this.i = i;
    }
    public void run() {
        T10.tmp+=T10.sample.charAt(i);
    }
}

以下是一些示例输出:

Mnla
Maniplua
Mpia
Miap
Mu

请告诉我们您希望从您的代码中得到什么输出。

一般来说:

在您的实施中,您确实启动了 10 个线程(因为您的 sample 字符串有 10 个字母)。但是此时你完全无法控制线程的执行顺序和tmp变量的状态

这可能会导致字母和字母的混合顺序相互覆盖(如您的输出所示)。

一旦您指定了您期望的输出,就可以提出解决方案建议。

首先,你需要知道两件事:

  • 不能更改Java中的字符串。看起来像的代码 修改字符串总是创建一个新字符串并丢弃 前一个
  • += 不是单个操作 - 它是三个操作 (阅读、修改、写回)。

您可以想象,在您的代码中,当两个线程同时读取字符串时,它们读取的是相同的值(例如“Man”)。然后第一个线程创建一个新字符串(添加自己的字母,例如“Mani”),第二个线程创建另一个新字符串(例如“Manp”)。现在他们都将对新值的引用放入字段 tmp;根据哪个“获胜”,其他线程永远不会看到其中一个字符。请注意,在“真实”程序中,问题更为复杂(开始优化),您确实需要了解 Java 内存模型才能编写正确的代码。

要解决您的问题,您需要:

  • 停止使用字符串(不能修改,新字符串需要 他们的位置),而是使用存储字符的可变对象;一种 所有线程都可以看到并可以写入的单个对象;

  • 确保此对象在与 多线程(在 Java 中,这意味着对象是 并发或同步)

实际上,Java 有一个非常古老的 class(如今很少使用)非常适合您的情况:StringBuffer.

为您的 tmp 使用 StringBuffer 而不是 String;然后使用 append('x') 而不是 += 'x' 来添加字符。