Неожиданная разница в поведении между использованием потока с использованием Runnable и производного класса Thread - PullRequest
1 голос
/ 07 марта 2011

В: Мне нужно подробное объяснение выходных данных следующих кодов ... В чем разница для потока, созданного с помощью запускаемого интерфейса, и потока, созданного непосредственно путем расширения класса потока ... ???

Q1:

public class BalanceChecker1{
    public static void main(String [] args) {
        RunnableClass runnableClass=new RunnableClass();
        new Thread(runnableClass).start();
        new Thread(runnableClass).start();
    }
}

class RunnableClass implements Runnable{
    Bean bean=new Bean();
    public void run(){
        synchronized(bean){
            bean.incBalance();
        }
    }
}

class Bean{
    private int balance=0;
    public void incBalance(){
        balance++;
        System.out.println(" The thread name "+Thread.currentThread().getName());
        System.out.println(" The balance is "+balance);
    }
}

ВЫХОД:

 The thread name Thread-0
 The balance is 1
 The thread name Thread-1
 The balance is 2

Q2:

public class BalanceChecker1{
    public static void main(String [] args){
        new specialThread().start();
        new specialThread().start();
    }
}
class specialThread extends Thread{
    Bean bean=new Bean();
    public void run(){
        synchronized(bean){
            bean.incBalance();
        }
    }
}

class Bean{
    private int balance=0;
    public void incBalance(){
        balance++;
        System.out.println(" The thread name "+Thread.currentThread().getName());
        System.out.println(" The balance is "+balance);
    }
}

ВЫХОД:

 The thread name Thread-0
 The thread name Thread-1
 The balance is 1
 The balance is 1

1 Ответ

6 голосов
/ 07 марта 2011

Важным отличием между этими двумя примерами является , а не в Runnable по сравнению с расширением Thread (на несвязанной ноте: почти никогда нет причин для расширения Thread, вы почти всегда хотите агрегат Runnable.

Важным отличием является то, что в первом примере оба запущенных потока совместно используют общий Bean объект, с которым они синхронизируются! Это означает, что вызов incBalance() не может быть выполнен обоими потоками одновременно.

Во втором примере каждый из них имеет отдельный Bean объект, поэтому синхронизация не имеет практического эффекта.

Также обратите внимание, что опубликованный вами вывод не гарантирован: вы можете получить тот же вывод во втором примере, что и в первом (однако вы не можете получить смешанный вывод из второго примера из первого).

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