Add basis of grouped thread factory and make the scheduler use it.

This commit is contained in:
md_5 2014-07-10 11:09:59 +10:00
parent 6615500f08
commit 705b554b3b
5 changed files with 63 additions and 14 deletions

View File

@ -1,11 +1,16 @@
package net.md_5.bungee.api.plugin; package net.md_5.bungee.api.plugin;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Logger; import java.util.logging.Logger;
import lombok.Getter; import lombok.Getter;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ConfigurationAdapter; import net.md_5.bungee.api.config.ConfigurationAdapter;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
/** /**
* Represents any Plugin that may be loaded at runtime to enhance existing * Represents any Plugin that may be loaded at runtime to enhance existing
@ -83,4 +88,19 @@ public class Plugin
this.file = description.getFile(); this.file = description.getFile();
this.logger = new PluginLogger( this ); this.logger = new PluginLogger( this );
} }
//
private ExecutorService service;
@Deprecated
public ExecutorService getExecutorService()
{
if ( service == null )
{
service = Executors.newCachedThreadPool( new ThreadFactoryBuilder().setNameFormat( getDescription().getName() + " Pool Thread #%1$d" )
.setThreadFactory( new GroupedThreadFactory( this ) ).build() );
}
return service;
}
//
} }

View File

@ -0,0 +1,34 @@
package net.md_5.bungee.api.scheduler;
import java.util.concurrent.ThreadFactory;
import lombok.Data;
import net.md_5.bungee.api.plugin.Plugin;
@Data
@Deprecated
public class GroupedThreadFactory implements ThreadFactory
{
private final ThreadGroup group;
public class BungeeGroup extends ThreadGroup
{
private BungeeGroup(String name)
{
super( name );
}
}
public GroupedThreadFactory(Plugin plugin)
{
this.group = new BungeeGroup( plugin.getDescription().getName() );
}
@Override
public Thread newThread(Runnable r)
{
return new Thread( group, r );
}
}

View File

@ -366,9 +366,9 @@ public class BungeeCord extends ProxyServer
t.printStackTrace(); t.printStackTrace();
} }
getScheduler().cancel( plugin ); getScheduler().cancel( plugin );
plugin.getExecutorService().shutdownNow();
} }
scheduler.shutdown();
getLogger().info( "Thank you and goodbye" ); getLogger().info( "Thank you and goodbye" );
// Need to close loggers after last message! // Need to close loggers after last message!
for ( Handler handler : getLogger().getHandlers() ) for ( Handler handler : getLogger().getHandlers() )

View File

@ -4,6 +4,7 @@ import java.security.AccessControlException;
import java.security.Permission; import java.security.Permission;
import java.util.logging.Level; import java.util.logging.Level;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
public class BungeeSecurityManager extends SecurityManager public class BungeeSecurityManager extends SecurityManager
{ {
@ -54,10 +55,12 @@ public class BungeeSecurityManager extends SecurityManager
} }
@Override @Override
public ThreadGroup getThreadGroup() public void checkAccess(ThreadGroup g)
{ {
checkRestricted( "Thread Creation: Use scheduler" ); if ( !( g instanceof GroupedThreadFactory.BungeeGroup ) )
return super.getThreadGroup(); {
checkRestricted( "Illegal thread group access" );
}
} }
@Override @Override

View File

@ -4,14 +4,12 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import gnu.trove.TCollections; import gnu.trove.TCollections;
import gnu.trove.map.TIntObjectMap; import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TIntObjectHashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
@ -21,7 +19,6 @@ import net.md_5.bungee.api.scheduler.TaskScheduler;
public class BungeeScheduler implements TaskScheduler public class BungeeScheduler implements TaskScheduler
{ {
private final ExecutorService s = Executors.newCachedThreadPool( new ThreadFactoryBuilder().setNameFormat( "Bungee Pool Thread #%1$d" ).build() );
private final AtomicInteger taskCounter = new AtomicInteger(); private final AtomicInteger taskCounter = new AtomicInteger();
private final TIntObjectMap<BungeeTask> tasks = TCollections.synchronizedMap( new TIntObjectHashMap<BungeeTask>() ); private final TIntObjectMap<BungeeTask> tasks = TCollections.synchronizedMap( new TIntObjectHashMap<BungeeTask>() );
private final Multimap<Plugin, BungeeTask> tasksByPlugin = Multimaps.synchronizedMultimap( HashMultimap.<Plugin, BungeeTask>create() ); private final Multimap<Plugin, BungeeTask> tasksByPlugin = Multimaps.synchronizedMultimap( HashMultimap.<Plugin, BungeeTask>create() );
@ -32,15 +29,10 @@ public class BungeeScheduler implements TaskScheduler
@Override @Override
public ExecutorService getExecutorService(Plugin plugin) public ExecutorService getExecutorService(Plugin plugin)
{ {
return s; return plugin.getExecutorService();
} }
}; };
public void shutdown()
{
s.shutdown();
}
@Override @Override
public void cancel(int id) public void cancel(int id)
{ {
@ -89,7 +81,7 @@ public class BungeeScheduler implements TaskScheduler
Preconditions.checkNotNull( task, "task" ); Preconditions.checkNotNull( task, "task" );
BungeeTask prepared = new BungeeTask( this, taskCounter.getAndIncrement(), owner, task, delay, period, unit ); BungeeTask prepared = new BungeeTask( this, taskCounter.getAndIncrement(), owner, task, delay, period, unit );
tasks.put( prepared.getId(), prepared ); tasks.put( prepared.getId(), prepared );
s.execute( prepared ); owner.getExecutorService().execute( prepared );
return prepared; return prepared;
} }