Getting started with Java LanguageInheritanceStreamsExceptions and exception handlingCollectionsLambda ExpressionsGenericsFile I/OArraysInterfacesMapsStringsInputStreams and OutputStreamsDefault MethodsClasses and ObjectsBasic Control StructuresConcurrent Programming (Threads)Console I/OSingletonsVisibility (controlling access to members of a class)Regular ExpressionsAutoboxingDocumenting Java CodeExecutor, ExecutorService and Thread poolsObject Class Methods and ConstructorJAXBPrimitive Data TypesNetworkingOptionalEnumsHttpURLConnectionAnnotationsAudioDate ClassCalendar and its SubclassesNashorn JavaScript engineJava Native InterfaceRemote Method Invocation (RMI)Iterator and IterableOperatorsAssertingScannerProperties ClassPreferencesReflection APIConstructorsByteBufferSerializationJSON in JavaRandom Number GenerationRecursionPolymorphismStringBuilderReference Data TypesBit ManipulationJava AgentsEncapsulationType ConversionBigIntegerBigDecimalRSA EncryptionVarargs (Variable Argument)ThreadLocalLogging (java.util.logging)Using the static keywordDisassembling and DecompilingResources (on classpath)log4j / log4j2JVM FlagsOracle Official Code StandardCharacter encodingJava Memory ManagementImmutable ObjectsObject CloningAlternative CollectionsListsBufferedWriterLocalTimeSetsComparable and ComparatorJVM Tool InterfaceNested and Inner ClassesApache Commons LangGetters and SettersThe ClasspathBytecode ModificationXML Parsing using the JAXP APIsReference TypesLocalization and InternationalizationJAX-WSXML XPath EvaluationJava Performance TuningParallel programming with Fork/Join frameworkCommon Java PitfallsNon-Access ModifiersJava Compiler - 'javac'XJCProcessInstalling Java (Standard Edition)Command line Argument ProcessingDates and Time (java.time.*)Fluent InterfaceXOM - XML Object ModelJust in Time (JIT) compilerFTP (File Transfer Protocol)Java Native AccessModulesJava Pitfalls - Exception usageJava Pitfalls - Language syntaxServiceLoaderClassloadersObject ReferencesJava Pitfalls - Performance IssuesCreating Images ProgrammaticallyAppletsNIO - NetworkingNew File I/OSecure objectsJava Pitfalls - Threads and ConcurrencySplitting a string into fixed length partsJava Pitfalls - Nulls and NullPointerExceptionSecurityManagerJNDIsuper keywordThe java.util.Objects ClassThe Java Command - 'java' and 'javaw'Atomic TypesJava Floating Point OperationsConverting to and from Stringssun.misc.UnsafeJava Memory ModelJava deploymentJava plugin system implementationsQueues and DequesRuntime CommandsNumberFormatSecurity & CryptographyJava Virtual Machine (JVM)Unit TestingJavaBeanExpressionsLiteralsJava SE 8 FeaturesJava SE 7 FeaturesPackagesCurrency and MoneyConcurrent CollectionsUsing ThreadPoolExecutor in MultiThreaded applications.Java Editions, Versions, Releases and DistributionsDynamic Method DispatchJMXSecurity & CryptographyGenerating Java CodeJShellBenchmarksCollection Factory MethodsMulti-Release JAR FilesStack-Walking APITreeMap and TreeSetSocketsJava SocketsUsing Other Scripting Languages in JavaFunctional InterfacesList vs SET2D Graphics in JavaClass - Java ReflectionDequeue InterfaceEnum MapEnumSet classLocal Inner ClassJava Print ServiceImmutable ClassString TokenizerFileUpload to AWSAppDynamics and TIBCO BusinessWorks Instrumentation for Easy IntegrationReaders and WritersHashtableEnum starting with numberSortedMapWeakHashMapLinkedHashMapStringBufferChoosing CollectionsC++ ComparisonCompletableFuture

CompletableFuture

Other topics

Convert blocking method to asynchonous

The following method will take a second or two depending on your connection to retrieve a web page and count the text length. Whatever thread calls it will block for that period of time. Also it rethrows an exception which is useful later on.

public static long blockingGetWebPageLength(String urlString) {
    try (BufferedReader br = new BufferedReader(new InputStreamReader(new URL(urlString).openConnection().getInputStream()))) {
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        return sb.toString().length();
    } catch (IOException ex) {
        throw new RuntimeException(ex);
    }
}

This converts it to a method that will return immediately by moving the blocking method call to another thread. By default the supplyAsync method will run the supplier on the common pool. For a blocking method this is probably not a good choice since one might exhaust the threads in that pool which is why I added the optional service parameter.

static private ExecutorService service = Executors.newCachedThreadPool();

static public CompletableFuture<Long> asyncGetWebPageLength(String url) {
    return CompletableFuture.supplyAsync(() -> blockingGetWebPageLength(url), service);
}

To use the function in an asynchronous fashion one should use on of the methods that accepts a lamda to be called with the result of the of the supplier when it completes such as thenAccept. Also it is important to use exceptionally or handle method to log any exceptions that might have happened.

public static void main(String[] args) {

    asyncGetWebPageLength("https://stackoverflow.com/")
            .thenAccept(l -> {
                System.out.println("Stack Overflow returned " + l);
            })
            .exceptionally((Throwable throwable) -> {
                Logger.getLogger("myclass").log(Level.SEVERE, "", throwable);
                return null;
            });

}

Simple Example of CompletableFuture

In the example below, the calculateShippingPrice method calculates shipping cost, which takes some processing time. In a real world example, this would e.g. be contacting another server which returns the price based on the weight of the product and the shipping method.

By modeling this in an async way via CompletableFuture, we can continue different work in the method (i.e. calculating packaging costs).

public static void main(String[] args) {
    int price = 15; // Let's keep it simple and work with whole number prices here
    int weightInGrams = 900;
    
    calculateShippingPrice(weightInGrams) // Here, we get the future
        .thenAccept(shippingPrice -> { // And then immediately work on it!
            // This fluent style is very useful for keeping it concise
            System.out.println("Your total price is: " + (price + shippingPrice));
        });
    System.out.println("Please stand by. We are calculating your total price.");
}


public static CompletableFuture<Integer> calculateShippingPrice(int weightInGrams) {
    return CompletableFuture.supplyAsync(() -> { 
        // supplyAsync is a factory method that turns a given 
        // Supplier<U> into a CompletableFuture<U>

        // Let's just say each 200 grams is a new dollar on your shipping costs
        int shippingCosts = weightInGrams / 200;
        
        try {
            Thread.sleep(2000L); // Now let's simulate some waiting time...
        } catch(InterruptedException e) { /* We can safely ignore that */ }

        return shippingCosts; // And send the costs back!
    });
}

Contributors

Topic Id: 10935

Example Ids: 32722,32724

This site is not affiliated with any of the contributors.