如何解决java.util.concurrent.RejectedExecutionException

时间:2017-03-20 11:15:42

标签: java android

我在此文件中有java.util.concurrent.RejectedExecutionException。正如我所看到的,onStop被调用后没有更多的进程在运行。不确定错误来自何处。而且我确信执行者没有得到它可以处理的更多任务。

请帮我弄清楚错误的来源。

public static final String TAG = BroadcastService.class.getSimpleName();

private static final int TIMER_DELAY_SECONDS = 3;

private volatile JmDNS mService = null;
private WifiManager.MulticastLock mMulticastLock = null;
private ScheduledExecutorService mExecutorService = null;
private ScheduledFuture mPublisherFuture = null;
private ScheduledFuture mApiPublisherFuture = null;

private NetworkUtils mNetworkUtils = null;

private Runnable mDelayedKiller = null;

public static Intent getStartIntent(Context context) {
    final Intent serviceIntent = new Intent(context, BroadcastService.class);
    serviceIntent.setAction(BroadcastService.INTENT_ACTION_BROADCAST_START);
    return serviceIntent;
}

public static Intent getStopIntent(Context context) {
    final Intent serviceIntent = new Intent(context, BroadcastService.class);
    serviceIntent.setAction(BroadcastService.INTENT_ACTION_BROADCAST_STOP);
    return serviceIntent;
}

@Override
public void onCreate() {
    super.onCreate();
    mNetworkUtils = NetworkUtils.getInstance(getApplicationContext());
}

@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
    if (intent == null) {
        return START_STICKY;
    }

    if (intent.getAction() != null) {
        switch (intent.getAction()) {
            case INTENT_ACTION_BROADCAST_START:
                startBroadcast();
                break;

            case INTENT_ACTION_BROADCAST_STOP:
                stopBroadcast();
                break;
        }
    }

    return START_STICKY;
}

@Nullable
@Override
public IBinder onBind(final Intent intent) {
    return null;
}

/**
 * Starts broadcast on a background thread
 */
public void startBroadcast() {
    if (mDelayedKiller != null) {
        NetworkThread.getCommonInstance().removeTask(mDelayedKiller);
        mDelayedKiller = null;
    }

    if (mExecutorService == null || mExecutorService.isShutdown()) {
        mExecutorService = Executors.newScheduledThreadPool(2);
    }

    if (mPublisherFuture != null) {
        mPublisherFuture.cancel(true);
    }

    final BonjourPublisher bonjourPublisher = new BonjourPublisher();
    mPublisherFuture = mExecutorService.schedule(bonjourPublisher, 2, TimeUnit.SECONDS);

    if (mApiPublisherFuture != null) {
        mApiPublisherFuture.cancel(true);
    }

    final ApiPublisher apiPublisher = new ApiPublisher();
    mApiPublisherFuture = mExecutorService.scheduleWithFixedDelay(apiPublisher, 0, 30, TimeUnit.SECONDS);

    //inform listeners
    EventBus.getDefault().post(new EventServiceBroadcasting(true));
}

public synchronized void stopBroadcast() {
    if (mPublisherFuture == null && mApiPublisherFuture == null) {
        return;
    }


    if (mPublisherFuture != null) {
        mPublisherFuture.cancel(true);
        if (mMulticastLock != null) {
            mMulticastLock.release();
            mMulticastLock = null;
        }
    }

    if (mApiPublisherFuture != null) {
        mApiPublisherFuture.cancel(true);
    }

    mDelayedKiller = new Runnable() {
        @Override
        public void run() {
            mExecutorService.shutdownNow();
            killService();
            stopSelf();
        }
    };

    NetworkThread.getCommonInstance().postDelayed(mDelayedKiller, 1000 * 20); //kill the service after 20 seconds

    //inform listeners
    EventBus.getDefault().post(new EventServiceBroadcasting(false));
}

@Override
public void onDestroy() {
    super.onDestroy();
    killService();
}

private synchronized void killService() {
    if (mService != null) {
        try {
            mService.unregisterAllServices();
            mService.close();
            mService = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
    }
}

public static class DiscoverableAssistant {

    private DiscoverableAssistant() {
    }

    public static boolean isDiscoverable(Context context) {
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        return prefs.getBoolean(PREF_DEVICE_DISCOVERABLE, true); //true by default
    }

    public static void setDiscoverable(Context context, boolean discoverable) {
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        prefs.edit().putBoolean(PREF_DEVICE_DISCOVERABLE, discoverable).apply();
    }
}

private class BonjourPublisher implements Runnable {

    @Override
    public void run() {

        final String serviceName = mNetworkUtils.getDeviceName(BroadcastService.this);
        final String serviceType = getString(R.string.multi_dns_network_name);

        final Map<String, String> properties = new HashMap<>();
        properties.put(DeviceViewActivity.DEVICE_PROPERTY_DEVICE_TYPE, "Android");
        properties.put(DeviceViewActivity.DEVICE_PROPERTY_FILE_SERVER_PORT,
                String.valueOf(mNetworkUtils.getAssignedPort()));
        if (DiscoverableAssistant.isDiscoverable(BroadcastService.this)) {
            properties.put(DeviceViewActivity.DEVICE_PROPERTY_DISCOVERABLE, "true");
        } else {
            properties.put(DeviceViewActivity.DEVICE_PROPERTY_DISCOVERABLE, "false");
        }

        //acquire wifi multicast lock
        if (mMulticastLock == null) {
            final WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
            mMulticastLock.setReferenceCounted(true);
            mMulticastLock.acquire();
        }

        try {
            if (mService == null) {
                mService = JmDNS.create(mNetworkUtils.getMyInet4Address(),
                        NetworkUtils.getHostName(mNetworkUtils.getDeviceName(BroadcastService.this)));
            }

            final ServiceInfo info = ServiceInfo.create(serviceType, serviceName, mNetworkUtils.getAssignedPort(), 0, 0, true, properties);
            while (mService != null) {
                mService.registerService(info);
                Thread.sleep(TIMER_DELAY_SECONDS * 1000);
                mService.unregisterAllServices();
                Thread.sleep(1000);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
        } catch (Exception e) {
        }
    }
}

private class ApiPublisher implements Runnable {

    private APo api = null;
    private SimplifiedDeviceInfo mDeviceInfo = null;

    public ApiPublisher() {
        api = Utils.getRetrofitInstance(BroadcastService.this, null)
                .create(api.class);
    }

    @Override
    public void run() {
        try {
            if (mDeviceInfo == null) {
                mDeviceInfo = new SimplifiedDeviceInfo(mNetworkUtils.getDeviceName(BroadcastService.this),
                        mNetworkUtils.getMyInet4Address().getHostAddress(), mNetworkUtils.getAssignedPort(),
                        NetworkUtils.getDeviceType(), BroadcastService.DiscoverableAssistant.isDiscoverable(BroadcastService.this));
            }

            Call<JsonElement> call = api.broadcastDevice(mDeviceInfo);
            call.execute();
        } catch (Exception e) {
        }
    }
}

1 个答案:

答案 0 :(得分:1)

当您尝试向执行程序提交任务时,抛出了RejectedExecutionException,并且它拒绝了它。在这种情况下,异常消息中有一条线索:

java.util.concurrent.ScheduledThreadPoolExecutor@42209b70[
    Sh‌​‌​utting down, pool size = 2, active threads = 2, 
    queued tasks = 0, completed tasks = 248]

这告诉我您正在尝试向正在关闭的Executor提交任务。

现在我不假装了解您的代码实际在做什么,但我可以看到您正在使用postThread来安排关闭执行程序的Runnable。我的猜测是,这已经做到了......然后你尝试提交另一项任务。

在阅读你的代码时,我发现了几个你抓到的地方,然后挤压Exception。这是一个非常糟糕的主意

如果这是您调试代码时遇到问题的原因,我不会感到惊讶。