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();
根据经验,线程之间的同步越多,使用线程获得的好处就越少。如果您希望某些事情按特定顺序发生,您应该在单个线程中按该顺序执行这些事情。
使用线程的诀窍是设计您的程序,以便它可以在顺序不重要的地方做有用的事情。
对于下面的程序,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();
根据经验,线程之间的同步越多,使用线程获得的好处就越少。如果您希望某些事情按特定顺序发生,您应该在单个线程中按该顺序执行这些事情。
使用线程的诀窍是设计您的程序,以便它可以在顺序不重要的地方做有用的事情。