JVM按顺序启动线程的运行()方法的保证是什么

what is the assurity for JVM to start run() method of Threads in a sequence

对于下面的程序,ans 是 --> 打印:printName,然后等待 5 秒,然后打印:printValue

但据我所知,由 JVM 来选择一个线程并启动它的 运行 方法。那么为什么它不能(printvalue printname 然后暂停 5 秒)。

注意:我了解同步方法的概念,但我们如何确定 JVM 将始终选择线程 t1 作为其第一个线程。

class B {
    public synchronized void printName() {
        try {
            System.out.println("printName");
            Thread.sleep(5 * 1000);
        } catch (InterruptedException e) {
        }
    }

    public synchronized void printValue() {
        System.out.println("printValue");
    }
}

public class Test1 extends Thread {
    B b = new B();

    public static void main(String argv[]) throws Exception {
        Test1 t = new Test1();
        Thread t1 = new Thread(t, "t1");
        Thread t2 = new Thread(t, "t2");
        t1.start();
        t2.start();
    }

    public void run() {
        if (Thread.currentThread().getName().equals("t1")) {
            b.printName();
        } else {
            b.printValue();
        }
    }
}

在此上下文中,synchronize 仅表示它们不能同时 运行,而不是它们必须按顺序 运行。如果你想让它们运行按顺序排列,那么你不需要线程,或者你想要一个更复杂的排队机制。

所以,你是对的,它可以是 "printName" 暂停 "printValue" "printValue" "printName" 暂停.

如果您多次 运行 该程序,您可能会更频繁地看到第一个程序。您偶尔会看到第二个输出。偏差是因为线程 1 上的 start() 和线程 2 上的 start() 之间存在轻微延迟。

how we are sure here that JVM will always pick the thread t1 as its first thread.

您可以永远确保t1 线程将在t2 线程启动运行 之前启动运行。如果你需要 t1 线程在 t2 线程做一些其他事情之前做一些事情,那么你将不得不使用一些同步对象(例如,一个 Semaphore)来让 t2 等待。

Semaphore semaphore = new Semaphore(0);

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        doTheThingThatHasToBeDoneFirst();
        semaphore.release();
        doOtherStuff();
    }
}).start();

Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        semaphore.acquire();  //will not return until t1 thread calls release().
        doOtherOtherStuff();
    }
}).start();

但这并不是使用线程的明智方法。为什么不直接这样做呢?

doTheThingThatHasToBeDoneFirst();

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        doOtherStuff();
    }
}).start();

Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        doOtherOtherStuff();
    }
}).start();

根据经验,线程之间的同步越多,使用线程获得的好处就越少。如果您希望某些事情按特定顺序发生,您应该在单个线程中按该顺序执行这些事情。

使用线程的诀窍是设计您的程序,以便它可以在顺序重要的地方做有用的事情。