* FOR JXTA MODULE IMPLEMENTATIONS ONLY. If you are simply using existing
* services on a peer group (pipe service, etc) then you should not use
* this task manager - use your own thread pools. If you are implementing
* a new service that will run on a peer group, then you must use this
* task manager for all asynchronous and periodic tasks.
* @return the task manager associated with this peer group.
*/
public TaskManager getTaskManager();
通过这个方法我们可以获得任务管理器对象。注释中说明:
该任务管理器应仅在JXTA模块的实现中使用。并且如果你只是简单的使用对等组中已经存在的服务(例如管道服务),那么你也不应该使用这个任务管理器——这种情况下应该使用你自己的线程池。如果你正在实现一个运行在对等组上的新服务,那么你必须为所有的异步和周期性的任务使用这个任务管理器。
那么这个任务管理器又是如何创建和如何销毁的呢?让我们从源代码中找找线索。
在此过程中,我们将主要涉及以下类/接口:
NetworkManager:
PeerGroup:
GenericPeerGroup:
* Provides common services for most peer group implementations.
*/
Platform:
* Provides the implementation for the World PeerGroup. The World peer group
* differs from other peer groups in the following ways :
* <ul>
* <li>The World Peer Group has no parent. It is the primordial peer group.
* </li>
* <li>The World Peer Group provides the default definition for the Network
* Peer Group. Peers are free to use alternate implementations for the
* Network PeerGroup.</li>
* <li>The World Peer Group is initialized with configuration parameters and
* the store home location.</li>
* </ul>
*/
StdPeerGroup:
* A subclass of GenericPeerGroup that makes a peer group out of independent
* plugin services listed in its impl advertisement.
*/
WorldPeerGroupFactory:A factory for instantiating the World Peer Group.
NetPeerGroupFactory:A factory for instantiating a Network Peer Group instances.
ShadowPeerGroup:
* ShadowPeerGroup is almost a regular StdPeerGroup, except that it borrows its
* parent's configuration. The only real use is for the Net Peer Group.
*/
CompatibilityUtils:
* General compatibility utility library for centralizing default
* compatibility information. This class should not be used by applications.
* It is merely a centralized location for the implementation classes to
* use. There are other, supported ways of accessing this information for
* application use.
*/
它们之间有如下关系:
从上面的注释(当然从源代码中会更清楚)可以看出:WorldPeerGroup是Platform的一个实例。
而在Platform中对任务管理器进行了初始化。可见任务管理器正是在Platform中实例化的。
在Platform中值得注意的两个地方是
public TaskManager getTaskManager() {
return taskManager;
}
@Override
public void stopApp() {
super.stopApp();
taskManager.shutdown();
}
在GenericPeerGroup中值得注意的地方是
return parentGroup.getTaskManager();
}
由于所有的PeerGroup都直接或间接继承至GenericPeerGroup,因此它们获取的任务管理器最终都是从WorldPeerGroup中实例化的那个任务管理器。
整个任务管理器的初始化过程如下:
此处可绘制时序图,暂缺。
下面看看任务管理器是如何销毁的。
首先 从上面的注释中可以看出NetPeerGroup是ShadowPeerGroup的一个实例。
在调用NetworkManager.stopNetwork()停止JXTA平台时,会调用ShadowPeerGroup(NetPeerGroup)的stopApp方法;在ShadowPeerGroup的stopApp方法中又会调用其父类(StdPeerGroup)的stopApp方法,在StdPeerGroup的stopApp方法中又会调用其父类(GenericPeerGroup)的stopApp方法。好了,到此为止,我们看到并没有看到Platform(即WorldPeerGroup)的stopApp方法被调用,那么taskManager.shutdown方法就没有机会执行。但是在
* {@inheritDoc}
* <p/>
* PeerGroupInterface's stopApp() does nothing. Only a real reference to the
* group object permits to stop it without going through ref counting.
*/
public void stopApp() {
stopping = true;
Collection<ModuleClassID> allServices = new ArrayList<ModuleClassID>(services.keySet());
// Stop and remove all remaining services.
for (ModuleClassID aService : allServices) {
try {
removeService(aService);
} catch (Exception failure) {
LOG.log(Level.WARNING, "Failure shutting down service : " + aService, failure);
}
}
if (!services.isEmpty()) {
LOG.warning(services.size() + " services could not be shut down during peer group stop.");
}
// remove everything (just in case);
services.clear();
getGlobalRegistry().unRegisterInstance(peerGroupAdvertisement.getPeerGroupID(), this);
// Explicitly unreference our parent group in order to allow it
// to terminate if this group object was itself the last reference
// to it.
if (parentGroup != null) {
// parentGroup.unref();
parentGroup = null;
}
// executors from TaskManager are now shutdown by the NetworkManager
// No longer initialized.
initComplete = false;
}
请看黄色底色的注释:来自任务管理器执行器现在已经被NetworkManager销毁。上面我们说到taskManager.shutdown方法根本就没有执行,这是怎么回事?
我比较了一下2.7版和2.5版GenericPeerGroup对于stopApp的实现,以下是2.5版stopApp的实现:
* {@inheritDoc}
* <p/>
* PeerGroupInterface's stopApp() does nothing. Only a real reference to the
* group object permits to stop it without going through ref counting.
*/
public void stopApp() {
stopping = true;
Collection<ModuleClassID> allServices = new ArrayList<ModuleClassID>(services.keySet());
// Stop and remove all remaining services.
for (ModuleClassID aService : allServices) {
try {
removeService(aService);
} catch (Exception failure) {
LOG.log(Level.WARNING, "Failure shutting down service : " + aService, failure);
}
}
if (!services.isEmpty()) {
LOG.warning(services.size() + " services could not be shut down during peer group stop.");
}
// remove everything (just in case);
services.clear();
globalRegistry.unRegisterInstance(peerGroupAdvertisement.getPeerGroupID(), this);
// Explicitly unreference our parent group in order to allow it
// to terminate if this group object was itself the last reference
// to it.
if (parentGroup != null) {
parentGroup.unref();
parentGroup = null;
}
// shutdown the threadpool
threadPool.shutdownNow();
scheduledExecutor.shutdownNow();
// No longer initialized.
initComplete = false;
}
可以看到2.5版中对线程池和执行器有显示的销毁。
可能的解释:
- 最理想的,也是最希望的,由于WorldPeerGroup(Platform)被解除引用(parentGroup=null),所有未完成的任务实例将被垃圾回收,从而达到销毁的目的。因此没有必要再显示销毁。但是这种依赖垃圾回收的方式应该是开发过程中着力避免的。
- Jxta平台的结束通常意味着整个程序的终结,没有必要再进行销毁。当然这种做法显得不那么优雅。
- 此处就是一个bug。可以在调用NetworkManager.stopNetwork()之前获得NetPeerGroup,并如下调用netPeerGroup.getTaskManager.shutdown();
当然目前来看这个问题没有什么大的影响。
整个任务管理器的销毁过程如下:
此处可绘制时序图,暂缺。
---------------------------------------------------------------------------------------------------------------------------------------
JXTA网络的启动顺序:
- If the JXTA network has already been started, nothing happens. The NetPeerGroup is alreadyavailable.
- Else, if no configuration is available, one is create beased on the specified connection mode.
- Then, an instance new of the NetPeerGroup factory class is created.
- The NetPeerGroup factory creates a WorldPeerGroup factory.
- The WorldPeerGroup factory creates a new WorldPeerGroup instance by fetching the name of the class corresponding to its default implemention in JXSE, that is: Platform. This is performed with the help of the JXTA loader.
- The services offered by the WorldPeerGroup are loaded and started.
- The implementation advertisements of the WorldPeerGroup and of its discovery service are published locally.
- A new instance of the NetPeerGRoup is created (using the ShadowPeerGroup class) and returned by the NetPeerGroup Factory. WorldPeerGroup is set as the parent peer group. The services of the NetPeerGroup object will have been started too.
傲轩游戏网