即使我们在 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'
来添加字符。
执行以下代码,但我希望它打印一个长度与 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'
来添加字符。