java.util.concurrent.RejectedExecutionException while shutting down SpeechClient

Viewed 4408

I am using Google Speech Client for converting speech to text, it is working fine but when I try to shut it down an exception is throwing.

This is the code I used for initialization.

private val mSpeechClient by lazy {

    applicationContext.resources.openRawResource(R.raw.credentials).use {
        SpeechClient.create(SpeechSettings.newBuilder()
                .setCredentialsProvider { GoogleCredentials.fromStream(it) }
                .build())
    }
}

But when I call

mSpeechClient.shutDown()

it is throwing this exception.

 Process: com.google.cloud.examples.speechrecognition, PID: 10080
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@11065d8d rejected from java.util.concurrent.ScheduledThreadPoolExecutor@3cbffe24[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 2]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2011)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:793)
    at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:298)
    at java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:503)
    at java.util.concurrent.ScheduledThreadPoolExecutor.execute(ScheduledThreadPoolExecutor.java:592)
    at io.grpc.internal.SerializingExecutor.schedule(SerializingExecutor.java:93)
    at io.grpc.internal.SerializingExecutor.execute(SerializingExecutor.java:86)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.closed(ClientCallImpl.java:594)
    at io.grpc.internal.DelayedStream$DelayedStreamListener$4.run(DelayedStream.java:418)
    at io.grpc.internal.DelayedStream$DelayedStreamListener.delayOrExecute(DelayedStream.java:372)
    at io.grpc.internal.DelayedStream$DelayedStreamListener.closed(DelayedStream.java:415)
    at io.grpc.internal.AbstractClientStream$TransportState.closeListener(AbstractClientStream.java:392)
    at io.grpc.internal.AbstractClientStream$TransportState.access$300(AbstractClientStream.java:200)
    at io.grpc.internal.AbstractClientStream$TransportState$1.run(AbstractClientStream.java:376)
    at io.grpc.internal.AbstractClientStream$TransportState.deframerClosed(AbstractClientStream.java:245)
    at io.grpc.internal.Http2ClientStreamTransportState.deframerClosed(Http2ClientStreamTransportState.java:31)
    at io.grpc.okhttp.OkHttpClientStream$TransportState.deframerClosed(OkHttpClientStream.java:275)
    at io.grpc.internal.MessageDeframer.close(MessageDeframer.java:233)
    at io.grpc.internal.MessageDeframer.closeWhenComplete(MessageDeframer.java:195)
    at io.grpc.internal.AbstractStream$TransportState.closeDeframer(AbstractStream.java:180)
    at io.grpc.internal.AbstractClientStream$TransportState.transportReportStatus(AbstractClientStream.java:379)
    at io.grpc.okhttp.OkHttpClientTransport.startGoAway(OkHttpClientTransport.java:739)
    at io.grpc.okhttp.OkHttpClientTransport.access$1900(OkHttpClientTransport.java:92)
    at io.grpc.okhttp.OkHttpClientTransport$ClientFrameHandler.run(OkHttpClientTransport.java:936)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    at java.lang.Thread.run(Thread.java:818)
1 Answers

RejectedExecutionException is thrown because new tasks were apparently submitted to the ThreadExecutor after it has been shut down. This happens due to the default handler policy set in ThreadExecutor - ThreadPoolExecutor.AbortPolicy.

  • In the default ThreadPoolExecutor.AbortPolicy, the handler throws a runtime RejectedExecutionException upon rejection.

Since you're shutting down manually your client mSpeechClient.shutDown() and inside of it the ThreadExecutor, to solve the problem you might want to change the handler policy to one of the following:

  • In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted.
  • In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed is simply dropped.
  • In ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not shut down, the task at the head of the work queue is dropped, and then execution is retried (which can fail again, causing this to be repeated.)

Above, is the explanation of the descriptions of handler policies cited from ThreadPoolExecutor JavaDoc.

To do this, you'd need to create a custom instance of ThreadExecutor with a policy setting of your choice, and then pass it to your client. This should solve the problem.

Related