同步线程以按顺序执行操作

时间:2016-11-26 21:43:25

标签: java multithreading synchronized

我有一个方法

public static synchronized void print(String message, int sleepTime) throws InterruptedException {
    System.out.println(message);
    Thread.sleep(sleepTime);
}

调用此方法会打印我给它的任何消息,并使调用它的线程暂停一段时间。 static synchronized使得这个类的多个线程必须同步它们的print,以便在另一个线程完成休眠之前没有线程可以开始打印(除了调用print的第一个线程之外当然)

我的代码中的其他地方,我有调用线程执行此操作:

print("some message", 1000);
print("some other message", 1000);

我使用此代码运行的每个试验都会导致所有线程首先打印第一条消息“some message”,然后所有线程最后打印“其他消息”。

例如,如果我有3个线程,预期结果如下(当我运行代码几次时,我可以得到它们):

some message
some message
some message
some other message
some other message
some other message

不可否认,我没有进行过那么多试验。

但是,我怀疑一个完成打印第一条消息的线程(让我们调用这个线程A)然后将与其他可能尚未打印第一条消息的线程竞争(让我们调用一个这样的线程B)。 调度程序是否有可能在第一次选择B之前第二次选择A,从而导致第二条消息在的某个地方打印第一条消息的所有实例都已完成打印?

换句话说,是否可能发生这种情况:

some message
some message
some other message
some message
some other message
some other message

如果可以采用上述顺序,我该如何确保不会发生这种情况?如何保证第一个序列是始终发生的序列?

3 个答案:

答案 0 :(得分:2)

这取决于你的意思。绝对没有禁止它的规则。但是,您正在使用的实现中所做的具体设计选择可能使其无法实际发生。

答案 1 :(得分:1)

  

调度程序是否有可能在选择之前第二次选择A.   B是第一次,从而导致打印第二条消息   在第一个消息的所有实例完成之前的某个地方   印刷?

是的,Thread调度程序可以再次选择相同的线程。

另外,您可能感兴趣并且需要仔细检查的一个参数是两个线程具有相同的优先级或NOT ,这可能会导致线程饥饿,如{{3}所述},这导致同一个线程一次又一次地运行。只需添加,您可以通过调用API here中提供的Thread将优先级设置为setPriority(int newPriority)

答案 2 :(得分:1)

绝对有可能。我运行了一个简单的多线程程序,它有3个Threads,我确实得到了你想要的联锁消息。

public class ThreadSyncTest {

    public static void main(String[] args) {

        ThreadSyncTest t = new ThreadSyncTest();
        TempThread r1 = t.new TempThread();
        Thread t1 = new Thread(r1);

        TempThread r2 = t.new TempThread();
        Thread t2 = new Thread(r2);

        TempThread r3 = t.new TempThread();
        Thread t3 = new Thread(r3);

        t1.start();
        t2.start();
        t3.start();

    }

    public static synchronized void print(String message, int sleepTime) throws InterruptedException {
        System.out.println(message);
        Thread.sleep(sleepTime);

    }

    class TempThread implements Runnable{

        @Override
        public void run() {
            while(true){
                try {
                    print("some message", 1000);
                    print("some other message", 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

    }


}

结果:

some message
some message
some other message
some message
some other message
some message
some message
some other message
some message
some other message