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

Java JVM按顺序启动线程的run()方法的保证是什么,java,multithreading,synchronization,Java,Multithreading,Synchronization,对于以下程序,ans为-->打印:打印名称,然后等待5秒钟,然后打印:打印值 但据我所知,由JVM选择一个线程并启动其run方法。所以为什么不能(printvalue printname,然后暂停5秒) 注意:我理解synchornized方法的概念,但我们如何确定JVM总是选择线程t1作为其第一个线程 class B { public synchronized void printName() { try { System.out.println

对于以下程序,ans为-->打印:打印名称,然后等待5秒钟,然后打印:打印值

但据我所知,由JVM选择一个线程并启动其run方法。所以为什么不能(printvalue printname,然后暂停5秒)

注意:我理解synchornized方法的概念,但我们如何确定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()
之间有一点延迟。

在这种情况下,
synchronize
只是意味着它们不能同时运行,而不是必须按顺序运行。如果希望它们按顺序运行,则不需要线程,或者需要更复杂的排队机制

因此,您是正确的,它可以是“printName”暂停“printValue”或“printValue”“printName”暂停


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

在这种情况下,
synchronize
只是意味着它们不能同时运行,而不是必须按顺序运行。如果希望它们按顺序运行,则不需要线程,或者需要更复杂的排队机制

因此,您是正确的,它可以是“printName”暂停“printValue”或“printValue”“printName”暂停


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

在这种情况下,
synchronize
只是意味着它们不能同时运行,而不是必须按顺序运行。如果希望它们按顺序运行,则不需要线程,或者需要更复杂的排队机制

因此,您是正确的,它可以是“printName”暂停“printValue”或“printValue”“printName”暂停

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

我们如何确定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();
        }
    }
}
您永远无法确定
t1
线程是否会在
t2
线程开始运行之前开始运行。如果您需要t1线程在t2线程执行其他操作之前执行某些操作,那么您必须使用一些同步对象(例如,
信号量
)使
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();
根据经验,线程之间的同步越多,使用线程的好处就越少。如果您希望某些事情以特定的顺序发生,您应该在单个线程中以该顺序完成这些事情

使用线程的诀窍是设计程序,以便在顺序无关紧要的情况下,它可以做一些有用的事情

我们如何确定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();
        }
    }
}
您永远无法确定
t1
线程是否会在
t2
线程开始运行之前开始运行。如果您需要t1线程在t2线程执行其他操作之前执行某些操作,那么您必须使用一些同步对象(例如,
信号量
)使
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();
根据经验,线程之间的同步越多,使用线程的好处就越少。如果您希望某些事情以特定的顺序发生,您应该在单个线程中以该顺序完成这些事情

使用线程的诀窍是设计程序,以便在顺序无关紧要的情况下,它可以做一些有用的事情

我们如何确定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();
        }
    }
}
您永远无法确定
t1
线程是否会在
t2
线程开始运行之前开始运行。如果您需要t1线程在t2线程执行其他操作之前执行某些操作,那么您必须使用一些同步对象(例如,
信号量
)使
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();
根据经验,线程之间的同步越多,使用线程的好处就越少。如果您希望某些事情以特定的顺序发生,您应该在单个线程中以该顺序完成这些事情

使用线程的诀窍是设计程序,以便在顺序无关紧要的情况下,它可以做一些有用的事情

我们如何确定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();
        }
    }
}
您永远无法确定
t1
线程是否会在
t2
线程开始运行之前开始运行。如果你需要