обработка потока ошибок в Java - PullRequest
0 голосов
/ 31 октября 2009
public class Test extends Thread{
    public void hello(String s){
        System.out.println(s);
    }
    public void run(){
        hello("I’mrunning...");
    }//endofrun()
    public static void main(String [] args){
        Test t=new Test();
    System.out.println("always first");
        t.start();

        System.out.println("always second but why?");
    } 
} 

Я запускал этот фрагмент кода 30 раз.

Почему "всегда второй, но почему?" всегда второй на консоли? Когда вызывается t.start (), у нас есть 2 потока. (2 стека): основная нить и вторая нить. так что «я бегу» иногда должен быть вторым выводом на консоли. Когда я удаляю оператор вывода «всегда первый», чем оставленные два выхода, веду себя недетерминированным (так и должно быть)

так, что не так в моем мышлении, почему System.out.println («всегда первый»); влияющих на параллелизм?

Ответы [ 4 ]

5 голосов
/ 31 октября 2009

Если вы сначала что-то записываете в консоль, вы, вероятно, будете влиять на то, когда происходит JIT-компиляция и, возможно, даже инициализация типа. Я не нахожу совершенно невероятным, что что-то подобное меняет наблюдаемый порядок. Я не удивлюсь, увидев, что программа ведет себя немного по-разному в разных системах и с разными JVM.

Дело в том, что любой из этих заказов полностью действителен. Вы не должны полагаться на то, что это одно или другое, и это не ошибка, если это всегда происходит одинаково. (Или, скорее, это может быть - но это не обязательно.)

Если вы хотите обеспечить определенный заказ, вам нужно сделать это явно - если вы не возражаете против того, в каком порядке происходят вещи, тогда нет проблем:)

1 голос
/ 31 октября 2009

Я запускал этот фрагмент кода 30 раз.

Запустите его еще семь миллиардов раз на каждую возможную комбинацию ОС и оборудования и сообщите о результатах. 30 очень низкое значение навсегда.

Почему "всегда второй, но почему?" всегда второй на консоли?

Сколько ядер у вас есть? Большинство планировщиков потоков предпочитают текущий запущенный поток по сравнению с вновь порожденным, особенно на одноядерных, и предпочитают синхронизировать потоки между ядрами в максимально позднюю точку (объект потока и System.out должны передаваться между потоками ОС ).

Учитывая, что многопоточность не является детерминированной, и большинство ОС не гарантирует честность и своевременность, это ни в коем случае не ошибка, что она ведет себя таким образом.

Если вы хотите явно упорядочить потоки, вам следует использовать либо синхронизированные блоки, либо более мощные классы в java.util.concurrent. Если вы хотите недетерминированное поведение, но разрешаете запуск другого потока, вы можете дать подсказку планировщику, используя Thread.yield().

public static void main ( String [] args ) 
{
    FirstThreadBug t = new FirstThreadBug();
    System.out.println ( "always first" );
    t.start();
    yield();
    System.out.println ( "always second but why?" );
}
0 голосов
/ 01 ноября 2009

Почему "всегда второй, но почему?" всегда второй на консоли?

Это не всегда второе. Мне удалось произвести оба порядка примерно за 5 выполнений вашего кода. Оба порядка действительны, а планирование потоков зависит от вашей ОС, а также, возможно, от JVM и от аппаратного обеспечения.

так, что не так в моем мышлении, почему System.out.println («всегда первый»); влияющих на параллелизм?

Ваше мышление правильно, ваши эксперименты вводят вас в заблуждение;)

0 голосов
/ 31 октября 2009

System.out.println("always first") всегда будет первым, потому что он приходит до запускается второй поток, поэтому он никогда не повлияет на параллелизм.

попробуйте поставить "всегда первое" предложение после t.start();, вы можете получить то, что ожидаете:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...