Java 如何在for循环中启动多个线程?
起初,在for循环中启动线程只是创建一个线程,然后启动它,但在for循环中,我决定打印线程名称和线程id,但发现只有最后创建的线程才是使用的线程Java 如何在for循环中启动多个线程?,java,multithreading,Java,Multithreading,起初,在for循环中启动线程只是创建一个线程,然后启动它,但在for循环中,我决定打印线程名称和线程id,但发现只有最后创建的线程才是使用的线程 public static void runSnipe(int threadsC) { NameSnipe NS = new NameSnipe(); Thread[] threads = new Thread[threadsC]; NS.DropTome = System.currentTimeMill
public static void runSnipe(int threadsC) {
NameSnipe NS = new NameSnipe();
Thread[] threads = new Thread[threadsC];
NS.DropTome = System.currentTimeMillis() + 500;
for (int i = 0; i < threadsC; i++)
{
Thread t = new Thread(NS);
threads[i] = t;
threads[i].setName(String.valueOf(i + 1));
NS.ThreadName = String.valueOf(threads[i].getName());
threads[i].start();
System.out.println(NS.ThreadName + " || " + threads[i].getName());
}
}
public class NameSnipe implements Runnable {
public long DropTome;
public String ThreadName;
@Override
public void run() {
long unixTimern = System.currentTimeMillis();
while (unixTimern < DropTome) {
unixTimern = System.currentTimeMillis();
}
System.out.println("Thread " + ThreadName + " done at " + System.currentTimeMillis());
}
}
发生这种情况是因为相同的可运行实例用于所有具有状态(
ThreadName
variable)的线程。每次执行循环时,ThreadName
变量都会更改为迭代器编号(i
)+1。所以对于最后一次迭代,它的值变为10。现在,由于所有线程都使用相同的runnable实例,因此所有线程在执行后都会打印值10。更好的方法是创建多个可运行对象以获取多个值。大概是这样的:
public static void runSnipe(int threadsC) {
Thread[] threads = new Thread[threadsC];
for (int i = 0; i < threadsC; i++)
{
NameSnipe NS = new NameSnipe();
NS.DropTome = System.currentTimeMillis() + 500;
Thread t = new Thread(NS);
threads[i] = t;
threads[i].setName(String.valueOf(i + 1));
NS.ThreadName = String.valueOf(threads[i].getName());
threads[i].start();
System.out.println(NS.ThreadName + " || " + threads[i].getName());
}
}
publicstaticvoidrunsnipe(int-threadsC){
线程[]线程=新线程[threadsC];
对于(int i=0;i
这是因为您在所有线程之间共享一个NameSnipe
对象。并且在迭代时不断修改它的名称。当线程开始读取ThreadName
值时,在for循环的最后一次迭代中将其设置为10
一个直接的解决方案是为每个线程创建一个单独的对象:
public class Main {
public static void main(String[] args) {
runSnipe(10);
}
private static void runSnipe(int threadsC) {
Thread[] threads = new Thread[threadsC];
for (int i = 0; i < threadsC; i++)
{
NameSnipe NS = new NameSnipe(); // create a separete NameSnipe per thread
NS.DropTome = System.currentTimeMillis() + 500;
Thread t = new Thread(NS);
threads[i] = t;
threads[i].setName(String.valueOf(i + 1));
NS.ThreadName = String.valueOf(threads[i].getName());
threads[i].start();
System.out.println(NS.ThreadName + " || " + threads[i].getName());
}
}
private static class NameSnipe implements Runnable {
long DropTome;
String ThreadName;
@Override
public void run() {
long unixTimern = System.currentTimeMillis();
while (unixTimern < DropTome) {
unixTimern = System.currentTimeMillis();
}
System.out.println("Thread " + ThreadName + " done at " + System.currentTimeMillis());
}
}
}
是的,它正在创建和启动n个线程,所有线程都在打印完Run:及其名称后立即结束 示例代码
public class ExecutorTest{
public static void main(String args[]){
int numberOfTasks = Integer.parseInt(args[0]);
ExecutorService executor= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
try{
for ( int i=0; i < numberOfTasks; i++){
executor.execute(new MyRunnable(i));
}
}catch(Exception err){
err.printStackTrace();
}
executor.shutdown(); // once you are done with ExecutorService
}
}
class MyRunnable implements Runnable{
int id;
public MyRunnable(int i){
this.id = i;
}
public void run(){
try{
System.out.println("Runnable started id:"+id);
System.out.println("Run: "+ Thread.currentThread().getName());
System.out.println("Runnable ended id:"+id);
}catch(Exception err){
err.printStackTrace();
}
}
}
这里发生了两件事1.)您一次又一次地更改同一对象的状态2)您已将500毫秒添加到NS.DropTome,并在run()中使用该时间,这会使所有线程进入run(),但等待条件通过。此时for循环已完成将ThreadName的值设置为10。只需更改NS.DropTome=System.currentTimeMillis()+500;至NS.DropTome=System.currentTimeMillis()+0;你自己看看有什么不同
1 || 1
2 || 2
3 || 3
4 || 4
5 || 5
6 || 6
7 || 7
8 || 8
9 || 9
10 || 10
Thread 1 done at 1595079627569
Thread 2 done at 1595079627569
Thread 6 done at 1595079627570
Thread 8 done at 1595079627570
Thread 9 done at 1595079627570
Thread 7 done at 1595079627570
Thread 10 done at 1595079627570
Thread 3 done at 1595079627570
Thread 4 done at 1595079627570
Thread 5 done at 1595079627570
public class ExecutorTest{
public static void main(String args[]){
int numberOfTasks = Integer.parseInt(args[0]);
ExecutorService executor= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
try{
for ( int i=0; i < numberOfTasks; i++){
executor.execute(new MyRunnable(i));
}
}catch(Exception err){
err.printStackTrace();
}
executor.shutdown(); // once you are done with ExecutorService
}
}
class MyRunnable implements Runnable{
int id;
public MyRunnable(int i){
this.id = i;
}
public void run(){
try{
System.out.println("Runnable started id:"+id);
System.out.println("Run: "+ Thread.currentThread().getName());
System.out.println("Runnable ended id:"+id);
}catch(Exception err){
err.printStackTrace();
}
}
}
java ExecutorTest 2
Runnable started id:0
Run: pool-1-thread-1
Runnable ended id:0
Runnable started id:1
Run: pool-1-thread-2
Runnable ended id:1