使用Runnable和派生Thread类的线程之间的行为意外差异

Cha*_*nth 1 java multithreading synchronization

问:我需要对以下代码的输出进行详细说明...使用runnable接口创建的线程和通过扩展线程类直接创建的线程有什么区别... ???

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

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

Joa*_*uer 6

这两个例子之间的重要区别在于Runnable扩展Thread(在一个不相关的注释中:几乎没有理由扩展Thread,你几乎总是想要实现Runnable.

重要的区别在于,在第一个示例中,两个正在运行的线程共享一个Bean它们同步的公共对象!这意味着incBalance()两个线程不能同时执行调用.

在第二个示例中,它们各自具有单独的Bean对象,因此同步没有实际效果.

另请注意,您发布的输出无法保证:您可以在第二个示例中获得与第一个相同的输出(但是您无法从第二个示例中获得第一个的混合输出).