All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.appengine.api.ThreadManager Maven / Gradle / Ivy

There is a newer version: 2.0.31
Show newest version
/*
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.appengine.api;

import com.google.apphosting.api.ApiProxy;
import java.util.Optional;
import java.util.concurrent.ThreadFactory;

/**
 * {@code ThreadManager} exposes a {@link ThreadFactory} that allows
 * App Engine applications to spawn new threads.
 *
 * Refer to 
 * this discussion of threads for drawbacks of thread usage and possible
 * alternatives.
 *
 */
public final class ThreadManager {
  private static final String REQUEST_THREAD_FACTORY_ATTR =
      "com.google.appengine.api.ThreadManager.REQUEST_THREAD_FACTORY";

  private static final String BACKGROUND_THREAD_FACTORY_ATTR =
      "com.google.appengine.api.ThreadManager.BACKGROUND_THREAD_FACTORY";

  /**
   * Returns a {@link ThreadFactory} which will create threads scoped to the current request. These
   * threads will be interrupted at the end of the current request and must complete within the
   * request deadline. If they fail to, the instance containing them may be terminated.
   *
   * 

The principal reason to use this method is so that the created threads can make App Engine * API calls ({@code com.google.appengine.api.*}). In general, threads not associated with a * request cannot make these API calls. * *

The returned factory is typically used with a call like {@link * java.util.concurrent.Executors#newCachedThreadPool(ThreadFactory)}. Do not use the {@link * java.util.concurrent.ExecutorService ExecutorService} returned by this call after the request * that created it has completed. * *

Note that calling {@link ThreadFactory#newThread} on the returned instance may throw any of * the unchecked exceptions mentioned by {@link #createBackgroundThread}. * * @throws NullPointerException if the calling thread is not associated with a request. */ public static ThreadFactory currentRequestThreadFactory() { ApiProxy.Environment environment = getCurrentEnvironmentOrThrow(); return (ThreadFactory) environment.getAttributes().get(REQUEST_THREAD_FACTORY_ATTR); } /** * Returns an Optional {@link ThreadFactory} which will create threads scoped to the current * request. These threads will be interrupted at the end of the current request and must complete * within the request deadline. If they fail to, the instance containing them may be terminated. * *

If this method is not called from an App Engine request thread, returns an empty Optional * instance. * *

The principal reason to use this method is so that the created threads can make App Engine * API calls ({@code com.google.appengine.api.*}). In general, threads not associated with a * request cannot make these API calls. * *

The returned factory is typically used with a call like {@link * java.util.concurrent.Executors#newCachedThreadPool(ThreadFactory)}. Do not use the {@link * java.util.concurrent.ExecutorService ExecutorService} returned by this call after the request * that created it has completed. * *

Note that calling {@link ThreadFactory#newThread} on the returned instance may throw any of * the unchecked exceptions mentioned by {@link #createBackgroundThread}. */ public static Optional currentRequestThreadFactoryOptional() { return Optional.ofNullable(ApiProxy.getCurrentEnvironment()) .flatMap( environment -> Optional.ofNullable( (ThreadFactory) environment.getAttributes().get(REQUEST_THREAD_FACTORY_ATTR))); } /** * Create a new {@link Thread} that executes {@code runnable} for * the duration of the current request. Calling this method is * equivalent to invoking {@link ThreadFactory#newThread} on the * ThreadFactory returned from {@link #currentRequestThreadFactory}. * This thread will be interrupted at the end of the current request * and must complete within the request deadline. If it fails to, * the instance containing it may be terminated. * * @throws IllegalStateException if you try to create more than 50 threads in a single request. * @throws NullPointerException if the calling thread is not associated with a request. * @throws ApiProxy.FeatureNotEnabledException If this application * cannot use this feature. */ public static Thread createThreadForCurrentRequest(Runnable runnable) { return currentRequestThreadFactory().newThread(runnable); } /** * Returns a {@link ThreadFactory} that will create threads that are * independent of the current request. * *

This ThreadFactory can currently only be used by backends. * *

Note that calling {@link ThreadFactory#newThread} on the * returned instance may throw any of the unchecked exceptions * mentioned by {@link #createBackgroundThread}. */ public static ThreadFactory backgroundThreadFactory() { ApiProxy.Environment environment = getCurrentEnvironmentOrThrow(); return (ThreadFactory) environment.getAttributes().get(BACKGROUND_THREAD_FACTORY_ATTR); } /** * Create a new {@link Thread} that executes {@code runnable} * independent of the current request. Calling this method is * equivalent to invoking {@link ThreadFactory#newThread} on the * ThreadFactory returned from {@link #backgroundThreadFactory}. * *

This method can currently only be used by backends. * * @throws ApiProxy.FeatureNotEnabledException If this application * cannot use this feature. * @throws ApiProxy.CancelledException If the request was interrupted * while creating the new thread. * @throws ApiProxy.ApiDeadlineExceededException If creation of the * new thread took too long. */ public static Thread createBackgroundThread(Runnable runnable) { return backgroundThreadFactory().newThread(runnable); } private static ApiProxy.Environment getCurrentEnvironmentOrThrow() { ApiProxy.Environment environment = ApiProxy.getCurrentEnvironment(); if (environment == null) { // IllegalStateException would make more sense, but this is compatible with code that // detected the absence of an environment by the NullPointerException it provoked due // to unprotected dereferences of `environment` in earlier versions. throw new NullPointerException( "Current thread is not associated with any request and is not a background thread"); } return environment; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy