繁体   English   中英

在没有任何同步的情况下使用线程打印一系列数字

[英]Print a sequence of numbers using threads without any synchronization

我正在尝试编写一个简单的代码来按顺序打印数字。 场景就像

1
2
3
4
5
.. and so on 

这是我写的代码

public class CounterThread implements Runnable {
    int counterNumber;

    public CounterThread(int counterNumber) {
        this.counterNumber = counterNumber;
    }

    @Override
    public void run() {
        System.out.println(this.counterNumber);
    }


    public static void main(String[] args) throws InterruptedException {
        int number = Integer.parseInt(args[0]);
        Thread[] listOfThreads = new Thread[number];
        for(int i = 1; i <= number; i++){
            CounterThread counterThread = new CounterThread(i);
            Thread thread = new Thread(counterThread);
            thread.start();
            listOfThreads[i-1] = thread;
        }

        for(Thread thread : listOfThreads){
            thread.join();
        }
    }
}
        

我意识到这对于线程编程来说是一种非常糟糕的编码实践,但我仍然处于新手级别,试图了解线程在同步和不同步时的行为方式。 output 是混乱的,这是可以预料的,但不是必需的。 我不确定我哪里出错了,非常感谢任何帮助。

你可以通过编写这个来优化你的代码,它只会让主线程等待当前thread完成它的执行。

for (int i = 1; i <= number; i++) {
    CounterThread counterThread = new CounterThread(i);
    Thread thread = new Thread(counterThread);
    thread.start();
    thread.join();
}

然而,这是一段非常奇怪的代码。 在这种情况下,不允许在多线程环境中使用synchronized ,最好 go 使用volatile关键字或原子变量。 这两种方法都旨在使对变量的所有写入和读取都是原子的。

volatile int number = 1; 

...

@Override
public void run() {
    System.out.println(number++);
}

... 

for (int i = 1; i <= number; i++) {
    CounterThread counterThread = new CounterThread();
    Thread thread = new Thread(counterThread);
    thread.start();
}

但是你应该注意, volatile并不能 100% 保证你会避免竞争条件。 特别是在这种情况下,因为number++不会是原子操作。 它实际上是number = number + 1 - 一次读取和一次写入。

但是对于Atomic ,递增将是一个原子操作,您可以编写类似

AtomicInteger number = new AtomicInteger(0);

...

@Override
public void run() {
    System.out.println(number.incrementAndGet());
}

您可以在start() join() ) 因为第一个循环中的方法开始导致它执行并且在到达下一个循环之前它已经完成了它的工作,所以您需要在开始后的第一个循环中调用它在开始下一个之前确保它的结束:

join() 方法允许一个线程等待另一个线程完成其执行。 如果 t 是线程 object,其线程当前正在执行,则 t.join() 将确保在程序执行下一条指令之前终止 t。

public class CounterThread implements Runnable {
    int counterNumber;

    public CounterThread(int counterNumber) {
        this.counterNumber = counterNumber;
    }

    @Override
    public void run() {
        System.out.println(this.counterNumber);
    }

    public static void main(String[] args) throws InterruptedException {
        int number = Integer.parseInt(args[0]);;
        for (int i = 1; i <= number; i++) {
            CounterThread counterThread = new CounterThread(i);
            Thread thread = new Thread(counterThread);
            thread.start();
            thread.join();
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM