简体   繁体   中英

How to solve java.util.concurrent.RejectedExecutionException

I have java.util.concurrent.RejectedExecutionException in this file. As I can see there is no more processes running after onStop called. Not sure where the error comes from. And I'm sure the executor isn't getting more tasks it can handle too.

Please help me to figure out where the error comes from.

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) {
        }
    }
}

The a RejectedExecutionException is thrown when you attempt to submit a task to an executor, and it is refuses it. In this case, there is a clue in the exception message:

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

This is telling me that you are attempting to submit a task to an Executor that is being shut down.

Now I can't pretend that I understand what your code is actually doing, but I can see that it is using postThread to schedule a Runnable that shuts down the executor. My guess is that the app has done that ... and then it is somehow trying to submit another task.

In reading your code I spotted a couple of places where you catch and then squash Exception . That is a really bad idea . I wouldn't be surprised if that is why you are having trouble debugging your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM