假设我们有这种情况:
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首先开始)或者“所有线程都准备好”的语句将在线程执行的中间弹出(例如:ChildThread2是'所有线程都准备好了'跑步)
所以我试图找到答案,我找到了这个网站:http://www.avajava.com/tutorials/lessons/how-do-i-use-threads-join-method.html 该网站基本上说当你使用start()
时没有保证执行顺序所以我可以假设这种奇怪的打印顺序是因为start()不保证执行顺序?这个理由是否也适用于“所有线程准备就绪”的问题?
答案 0 :(得分:4)
线程的全部意义在于它们可以同时执行。如果要确保完成任务的特定顺序,则必须放弃使用线程或使用显式同步。
所以我可以假设这种奇怪的打印顺序是因为start()不能保证执行顺序吗?
没错。当你start
一个线程时,主线程和新创建的线程之间基本上存在竞争条件。这意味着没有什么可以说两个线程之间发生事情的相对顺序。如果要确保特定排序,请使用同步。
答案 1 :(得分:1)
所以我可以假设这种奇怪的打印顺序是因为start()不能保证执行顺序吗?
是。你是对的。
这个理由是否也适用于“所有线程都准备就绪”的问题?
是。再一次。您的SOP
由主线程运行。因此,t1
可能会在main
有机会执行SOP
之前打印一些内容。
答案 2 :(得分:1)
启动线程时,启动的线程并行运行所有已运行的线程。线程调度程序调度可用处理器上的各种线程,每个线程获得一些处理器时间,每个线程轮流。但是处理器,分配给每个线程的顺序和时间取决于操作系统线程调度程序,你绝对不能保证。
答案 3 :(得分:1)
在Thread Execution中维护排序的简便方法是使用Semaphore
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();
}
}