gpt4 book ai didi

java - 如何创建线程以避免 IllegalThreadStateException

转载 作者:太空宇宙 更新时间:2023-11-04 12:40:34 25 4
gpt4 key购买 nike

这是一个多线程练习,我使用监视器来同步线程。我的监视器或同步没有问题,没有死锁。我想在主线程中创建一些线程。下面的代码生成线程,将它们添加到 ArrayList 并启动它们。使用 switch-case 生成不同的线程。由于每个线程都应添加到 ArrayList 并启动,因此我将这两行放在 switch-case 的末尾,以免在每个 case-state 中编写相同的代码。但这样它就会引发 IllegalThreadStateException。

为了使我的代码正常工作,我可以应用不同的方法,但我对所有这些方法都有一些疑问。哪一种是最合适的方法?

创建一个函数,该函数将创建一个新的 myThread 实例,将其添加到 ArrayList 中并启动它。但由于我必须从 main 调用它,或者它应该是静态的(据我所知,没有充分理由创建静态函数不是一个好习惯),或者我应该像 new myClass().someMethod() 那样调用它,但由于我必须创建许多新线程,它会创建许多 myClass 实例,看起来不太好。

public class myClass {

public static void main(String[] args) {

int scount=10, tcount=5, pcount=5;
final int SIZE = 20;


ArrayList<User> users = new ArrayList<User>();
myMonitor monitor = new myMonitor(SIZE);
User u = null;
int s = 0, t = 0, p = 0; //counters

//GENERATED CASUALLY DIFFERENT TYPE OF THREADS
while(s < scount || t < tcount || p < pcount){

int type = (int)(Math.random() * 3);

switch(type){
case 0:
if(p < pcount){
u = new User(monitor, p, "USER_TYPE_1");
p++;
}
break;
case 1:
if(t < tcount){
u = new User(monitor, p, "USER_TYPE_2");
t++;
}
break;
case 2:
if(s < scount){
u = new User(monitor, p, "USER_TYPE_2");
s++;
}
break;
}
users.add(u);
u.start();
}

}

}
<小时/>
public class User extends Thread{
myMonitor monitor;
final private int number;
final private String type;
final private int k;
final private int MIN = 1;
final private int MAX = 5;


public User(myMonitor monitor, int number, String type) {
this.monitor = monitor;
this.number = number;
this.type = type;
this.k = (int)(Math.random() * ((MAX - MIN) + 1)) + MIN;
}

public int getNumber() {
return number;
}

public String getType() {
return type;
}

@Override
public void run(){

for(int i=0; i<k; i++){

switch(this.type){
case "TYPE1":
monitor.startType1();
break;
case "TYPE2":
monitor.startType2(i);
break;
case "TYPE3":
monitor.startType3();
break;
}

try{

Long duration = (long) Math.ceil(Math.random() * 1000);
Thread.sleep(duration);
System.out.printf("%s-%d used system for the %d.time. Took %d ms\n",
this.type, this.number, i+1, duration);
} catch (InterruptedException e) {
e.printStackTrace();
}

switch(this.type){
case "TYPE1":
monitor.endType1();
break;
case "TYPE2":
monitor.endType2(i);
break;
case "TYPE3":
monitor.endType3();
break;
}

try{
Long duration = (long) Math.ceil(Math.random() * 1000);
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}

}
System.out.printf("%s-%d finished\n", this.type, this.number);
}

}

最佳答案

让我们进行一个思想实验,Math.random * 3 总是返回 0 - 这是可能的,因为它显然是 random (只是不太可能)。

迭代 1

int s == t == p == 0 

我们输入第一种情况,即type == 0。我们生成一个新的“P”Thread,并将其添加List中,并start()它。

p++

迭代 2

int s == t == 0; p == 1 

我们输入第一种情况,即type == 0。我们生成一个新的“P”Thread,并将其添加List中,并start()它。

p++

...

迭代 5

int s == t == 0; p == 4 

我们输入第一种情况,即type == 0。我们生成一个新的“P”Thread,并将其添加List中,并start()它。

p++

迭代 6

int s == t == 0; p == 5

我们输入第一种情况,即type == 0当 p >= pcount 时我们什么都不做。我们的 thrd 仍然指向我们在迭代 5 中创建的 Thread

我们将相同的Thread添加到Liststart()它。

IllegalThreadStateException

现在,显然 Math.random * 3 将返回不同的值,但它会返回重复值(并且您的代码是围绕该值设计的) - 所以您遇到这种情况。

如何避免?好吧,您实际上并不想要生成随机数:

final List<Integer> desiredValues = new ArrayList<>(Arrays.asList(0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2));
Collections.shuffle(desiredValues)
for(final Integer value : desiredValues) {
//case switch
}

关于java - 如何创建线程以避免 IllegalThreadStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36870353/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com