Java 加斯顿和阿尔方斯的例子:如何进入弓背?
我对这个例子总是有困难。这似乎是一种不必要的复杂方式来展示其试图实现的概念: 所以我的问题与同步或锁定无关;这可能与匿名类有关: 这只是如何访问bow方法中调用的bowBack中的代码?实现runnable的匿名类被传递给bow()方法Java 加斯顿和阿尔方斯的例子:如何进入弓背?,java,anonymous-class,Java,Anonymous Class,我对这个例子总是有困难。这似乎是一种不必要的复杂方式来展示其试图实现的概念: 所以我的问题与同步或锁定无关;这可能与匿名类有关: 这只是如何访问bow方法中调用的bowBack中的代码?实现runnable的匿名类被传递给bow()方法 也许这是个糟糕的问题。但是,用匿名类说明死锁会给示例带来不需要的复杂性,这是对的吗?方法调用bowback;这就是你的意思吗?您问“如何访问bowback方法中调用的bowback中的代码”,我不确定您的其他意思…bow方法调用bowback;这就是你的意思吗
也许这是个糟糕的问题。但是,用匿名类说明死锁会给示例带来不需要的复杂性,这是对的吗?方法调用
bowback
;这就是你的意思吗?您问“如何访问bowback方法中调用的bowback中的代码”,我不确定您的其他意思…bow方法调用bowback
;这就是你的意思吗?您会问“bowback中在bow方法中调用的代码是如何访问的”,我不确定您还想说什么…第一个匿名内部类的运行
方法调用
alphonse.bow(gaston)
gaston.bow(alphonse)
bow
方法依次调用具有调用效果的bower.bowBack(this)
gaston.bowBack(alphonse)
第二个匿名内部类的run
方法调用
alphonse.bow(gaston)
gaston.bow(alphonse)
最后是什么
alphonse.bowBack(gaston)
在考虑到两个Runnable
实例由不同的线程运行,并且bow
和bowBack
方法是同步的之前,这些都不是很有趣的。因此,我们的情况如下:
- 呼叫
,锁定alphonsealphonse.bow
- 打电话给加斯顿。后弓,把门锁在加斯顿身上
- 打电话给加斯顿。船头,把门锁在加斯顿身上
- 呼叫
,锁定alphonsealphonse.bowBack
Runnable
的实例,其run
方法在新创建的线程上执行。创建可运行的(至少在Java8之前)最简洁的方法是使用匿名内部类
匿名内部类的替代方法(同样,在Java8之前)是使用命名类。这会给示例增加混乱,我不认为这会让它更容易理解。(再说一次,我对匿名内部类很满意。)
Java 8的替代方案是使用lambdas而不是匿名内部类:
new Thread(() -> alphonse.bow(gaston)).start();
new Thread(() -> gaston.bow(alphonse)).start();
这使示例更加简洁,尽管如果您不熟悉lambdas,这可能没有帮助
目前,对于本例来说,使用匿名内部类是在不同线程上运行代码的合理方式
很难想出有效的方法来简化这个例子。目前,两个线程、两个对象和两个方法调用具有相当令人满意的对称性。主线程对单个子线程的死锁是可能的,但这会破坏对称性。也可以让两个线程死锁调用不同对象上的单个方法。这将使示例变得更短,但可能会令人困惑,因为单个方法将被调用四次:在两个对象上调用一次,从两个线程中调用一次。它可能更难理解,也更难解释。第一个匿名内部类的run
方法调用
alphonse.bow(gaston)
gaston.bow(alphonse)
bow
方法依次调用具有调用效果的bower.bowBack(this)
gaston.bowBack(alphonse)
第二个匿名内部类的run
方法调用
alphonse.bow(gaston)
gaston.bow(alphonse)
最后是什么
alphonse.bowBack(gaston)
在考虑到两个Runnable
实例由不同的线程运行,并且bow
和bowBack
方法是同步的之前,这些都不是很有趣的。因此,我们的情况如下:
第一根线
- 呼叫
alphonse.bow
,锁定alphonse
- 打电话给加斯顿。后弓,把门锁在加斯顿身上
第二线
- 打电话给加斯顿。船头,把门锁在加斯顿身上
- 呼叫
alphonse.bowBack
,锁定alphonse
或者,更简洁地说:
第一条线锁定阿尔方斯,然后锁定加斯顿
第二条线锁定加斯顿,然后锁定阿尔方斯
这很容易导致这样一种情况:第一个线程已经锁定了alphonse,第二个线程已经锁定了gaston,两个线程都无法继续,因为它正在等待另一个线程持有的锁。这就是本例所说明的死锁
现在您询问了匿名内部类。其中一个要点是,有多个线程在对象和锁上交互。如果只有一个线程,就不会死锁。如何让代码在另一个线程上运行?最简单的方法是创建一个线程,并向其传递一个Runnable
的实例,其run
方法在新创建的线程上执行。最简洁的方式