Java线程连接创建线程的顺序运行

Java线程连接创建线程的顺序运行,java,multithreading,concurrency,Java,Multithreading,Concurrency,当我运行下面的代码时,程序永远不会退出并卡在while循环中,这应该是预期的行为 public class MyClass implements Runnable { public static final int NO_OF_THREADS = 100; private static int count; private static Set<Integer> set = new HashSet<>(); @Override pu

当我运行下面的代码时,程序永远不会退出并卡在while循环中,这应该是预期的行为

public class MyClass implements Runnable {
    public static final int NO_OF_THREADS = 100;
    private static int count;
    private static Set<Integer> set = new HashSet<>();
    @Override
    public void run() {
        for(int i=0 ;i<10000; i++) {
            set.add(count++);
        }
    }
    public static void main(String[] args) throws Exception {
        Thread[] threadArray = new Thread[NO_OF_THREADS];
        for(int i=0; i<NO_OF_THREADS; i++) {
            threadArray[i] = new Thread(new MyClass());
        }
        for(int i=0; i<NO_OF_THREADS; i++) {
            threadArray[i].start();
            //threadArray[i].join();
        }
        while(set.size()!=1000000) {}
    }
}
公共类MyClass实现可运行{
公共静态final int NO_OF_线程=100;
私有静态整数计数;
私有静态集=新HashSet();
@凌驾
公开募捐{

对于(int i=0;i是这是预期的行为,当您的连接被注释时,多个线程将在同一时间访问您的集合,您将有竞争条件,在这种情况下,多个线程的计数将相同,因此基本上您将在同一位置添加多个元素,因此您将不会有预期的i数tems在集合中,因此循环条件将始终为真,并且您的应用程序不会退出


如果您的联接没有注释,则主线程将被阻塞,直到每个线程完成为止。当第一个线程启动并且主线程移动到联接时,主线程将被阻塞,并等待第一个线程完成,然后再移动到循环的下一个迭代,因此您将无法同时访问“count”因此,所有添加的元素都将是不同的

,在注释时称为竞态条件,而在未注释时称为竞态条件。这就是问题所在。未注释时没有竞态,因为
连接
强制主线程在启动新线程之前等待线程完成。因此一次只能有一个线程。@litite,我真傻,竟然把连接放在循环中。谢谢!@azuri,如果我是老师,我会教我的学生使用
Executors。newFixedThreadPool(n)
在教他们使用
线程之前
。我的问题不是关于第一种情况,即我同意争用条件是重复计数值的原因。我的问题是,当我取消对join()的注释时,为什么在第二种情况下没有争用条件@azuri i为其添加了一个解释,请检查它。
HashSet
的当前变异也会导致许多问题。有关@azuri的详细信息,请参阅此问题