Java 如何在for循环中启动多个线程?

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

起初,在for循环中启动线程只是创建一个线程,然后启动它,但在for循环中,我决定打印线程名称和线程id,但发现只有最后创建的线程才是使用的线程

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