【问题标题】:Execution order of multiple threads多线程的执行顺序
【发布时间】:2012-11-05 08:06:58
【问题描述】:

假设我们有这种情况:

class Stack{

public void main{

ChildThread1 t1 = new ChildThread1;
ChildThread1 t2 = new ChildThread1;
ChildThread1 t3 = new ChildThread1;

//then we make some ChildThread2 objects and some ChildThread3 objects

ChildThread2 s1 = new ChildThread2;
//...

ChildThread3 v1 = new ChildThread3;
//...

//now we let all threads start in mix order
t1.start();
v1.start();
//...

SOP("All threads are ready");

//then we let them run with join()
t1.join();
t2.join();
t3.join();

s1.join();
//...

v1.join();
//...

每种类型的线程在运行时都会打印出自己独特的语句。

我注意到每次执行程序时,输出总是不同的。例如,来自 ChilThread1 t1 的语句将在输出中间打印而不是开始(因为 t1 首先开始)或者语句“所有线程都准备好”将在线程执行中间弹出(例如:ChilThread2 是'所有线程都准备好了' 运行)

所以我试图找到答案,我找到了这个网站:http://www.avajava.com/tutorials/lessons/how-do-i-use-threads-join-method.html 该网站基本上说当你使用 start() 时没有保证执行顺序

所以我可以假设这种奇怪的打印顺序是因为 start() 不保证执行顺序吗?这个原因是否也适用于“所有线程都准备好”的问题?

【问题讨论】:

  • new ChildThread1 应该是new ChildThread1()
  • 我从来不明白这些问题。如果您想要或期望特定的执行顺序,您为什么要使用线程?如果您不知道线程的用途,为什么还要使用线程?
  • @EJP 每个人都必须在某一时刻学习。为什么要敌对?以一种能教会他新东西的方式回答他的问题。
  • 我不是说我想要订购,我只是假设在我阅读那篇文章之前它会按顺序打印。

标签: java multithreading


【解决方案1】:

线程的全部意义在于它们可以并发执行。如果您想确保完成事情的特定顺序,您要么必须放弃使用线程,要么使用显式同步。

所以我可以假设这种奇怪的打印顺序是因为 start() 不保证执行顺序吗?

没错。当您start 一个线程时,主线程和新创建的线程之间基本上存在竞争条件。这意味着对于两个线程之间发生的事情的相对顺序无话可说。如果要确保特定的顺序,请使用同步。

【讨论】:

  • 感谢您的评论。我不想要这个例子的特定顺序,我认为在我看到那篇文章之前它会按顺序打印。
【解决方案2】:

当您启动一个线程时,启动的线程会与所有已经运行的线程并行运行。线程调度程序在可用处理器上分派各种线程,每个线程轮流获得一些处理器时间。但是处理器,分配给每个线程的顺序和时间取决于操作系统线程调度程序,您绝对无法保证。

【讨论】:

    【解决方案3】:

    保持线程执行顺序的简单方法是使用信号量

    public class Semaphore {
    
    int value;
    
    public Semaphore(int intialValue) {
        this.value = intialValue;
    }
    
    public synchronized void p() {
        while (value <= 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
            }
    
        }
        value = value - 1;
    }
    
    public synchronized void v() {
        value = value + 1;
        this.notify();
    }
    

    }

    public class ThreadSync {
    
    static Semaphore semaphore = new Semaphore(0);
    
    public static void main(String[] args) {
        // t1 should be executed before t2
        Thread t1 = new Thread(new Runnable() {
    
            @Override
            public void run() {
                semaphore.p();
                System.out.println("executing " + Thread.currentThread().getName());
            }
        });
        Thread t2 = new Thread(new Runnable() {
    
            @Override
            public void run() {
                System.out.println("executing " + Thread.currentThread().getName());
                semaphore.v();
            }
        });
    
        t1.setName("Thread 1");
        t2.setName("Thread 2");
        t2.start();
        t1.start();
    
    }
    

    }

    【讨论】:

      【解决方案4】:

      所以我可以假设这种奇怪的打印顺序是因为 start() 不保证执行顺序吗?

      是的。你是对的。

      这个原因是否也适用于“所有线程都准备好”的问题?

      是的。又对了。您的 SOP 由主线程运行。所以,t1 有可能在main 有机会执行它之前打印一些东西是SOP

      【讨论】:

      • 谢谢。 '所有线程都准备好'打印在不同地方的部分让我觉得有问题。
      • 这种类型的输出是否意味着它还不是原子的?
      • @user977151:这里的原子是什么意思?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      相关资源
      最近更新 更多