Не все потоки используются для вызова методов

#java #multithreading

Вопрос:

Я использую конструктор потоков для создания потоков. Я ожидал, что приведенный ниже код будет выполняться 3 отдельными потоками и разными выходами. Может ли кто-нибудь, пожалуйста, объяснить, почему вывод отличается от моего понимания(почему поток 2 используется для вызова m1 дважды, а не t3)?

Код:-

 public static void main( String[] args ) {
        new SynchronizedExample().execute();
}

void execute() {
    SynchronizedExample s1 = new SynchronizedExample();

    Thread t1 = new Thread(s1::m1);
    Thread t2 = new Thread(s1::m1);
    Thread t3 = new Thread(s1::m2);
    t1.start();
    t2.start();
    t3.start();
}

public synchronized void m1(){
    try {
        System.out.println("Current Thread - "   Thread.currentThread().getName());
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("M1");
}

public void m2() {
    System.out.println("M2");
}
}
 

Выход:-

 Current Thread - Thread-0
M2
M1
Current Thread - Thread-1
M1
 

Ожидаемый Результат:-

 Current Thread - Thread-0
M2
Current Thread - Thread-1
M1
Current Thread - Thread-2
M1
 

Комментарии:

1. m2 не распечатывает текущее имя потока. Таким образом, результат будет именно таким, как вы ожидали. Нить 0 подобрана m1 , и Current Thread - Thread-0 затем печатается M1 . Пока это происходит, поток 2 поднялся m2 и просто печатает m2 . Поток 1 подобрал другого m1 (в какой-то момент, не могу сказать), но не может начать, потому что метод synchronized , поэтому печатает Current Thread - Thread-1 , а затем M1 , как только Поток 0 уронил монитор.

2. У вас нет a System.out.println("Current Thread - " Thread.currentThread().getName()); в m2, и m2 не синхронизирован.

3. Кстати, выходные данные из потоковых вызовов System.out.println не всегда отображаются на консоли в хронологическом порядке. Всегда включайте метку времени, например, Instant.now() для изучения, если вы хотите увидеть истинную последовательность. Или используйте потокобезопасную коллекцию для выходных строк, а не System.out .

Ответ №1:

Ты все запутал.

Я прокомментирую ваш вывод:

 Current Thread - Thread-0 [t1 - m1]
M2 [t3 - m2]
M1 [t1 - m1]
Current Thread - Thread-1 [t2 - m1]
M1 [t2 - m1]
 

Ваш код что-то печатает, затем ждет, затем печатает еще. Таким образом, один метод получает свои строки System.out, размазанные по первой и третьей строке. Ваш метод m2 вообще не печатается Current Thread - ... , так что то, чего вы ожидаете, очевидно, не может произойти. Добавьте отпечаток.

Комментарии:

1. Спасибо! с моей стороны это был отличный обзор.