多个线程的执行顺序

时间:2012-11-05 08:06:59

标签: java multithreading

假设我们有这种情况:

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()不保证执行顺序?这个理由是否也适用于“所有线程准备就绪”的问题?

4 个答案:

答案 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();

}

}