Showing posts with label concurrency. Show all posts
Showing posts with label concurrency. Show all posts

Friday, December 26, 2014

ExecutorService Conundrum

I was asked by someone to solve a problem with threads that they were having. They wanted to cancel a Future that was sent to an ExecutorService. I told them to look at a previous posts I had done on the subject. However, they insisted that this was different. So I took a look at the code. Alas, it was slightly different, but like most folks including me, they were too close to the problem to see the answer. I looked at it, and at first glance I thought something was askew, but it was not.

The code for this project can be downloaded here: runnable-example
As you can see from the results of the run, the future is canceled, but still keeps running. Then it gets interrupted, and breaks. So the question is why is it still running after being canceled.

Here is the Runnable and the main class to execute it:

MyRunnable.java


Main.java


So the do you have an answer? The answer is at the bottom of the blog. Don't peek... think!

Reference

Answer

Simply because you have canceled it, and even interrupted it; it is still a running thread. It is not scheduled, so you are not canceling it before execution.

Thursday, January 16, 2014

How do you cancel a scheduled Thread in an ExecutorService?

Executors in the Middle Ages
Humm... I thought...

I was asked this question a while ago, and I came up with a quick solution since it was just a general question. I went back and cleaned up my example which uses Callable and Future to demonstrate the concurrency libraries in Java.

In the example, I use a ExecutorService with a fixed thread pool size of two (2), to make the code slower to demonstrate the point. You can manipulate the value to see the effect on the code execution.

The code is to demonstrate you can do it,  there may be other cleaner ways of doing this. If you have an example, or idea on how to do it cleaner, please comment. :-)

Solution

The code for the project was developed using NetBeans and can be downloaded from Bitbucket at the link below. It is a NetBeans (Apache Ant) based project and should work with Ant without NetBeans.

CallOrderCancel

CallOrderCancel.java


Monday, September 09, 2013

ExecutorService and CountDownLatch Example

Image from Jeff Blogs
One of the most difficult concepts in teaching programming is threads. If you don't do a lot of thread programming, that knowledge has a quick way of being replaced in your mind.

Today, modern frameworks especially Java EE make thread programming even less apparent to the developer.

I had a very highly asynchronous application that was generating data based on examining data returned from a measurement sensor in a grain silo. The sensor was generating a lot of data especially as the silo was being filled, or emptied. I had a Java application that was generating real-time data that would start/stop various hardware based on how full, or empty the silo was. This application was also generating data charts. We have one big giant potential mess if the application does not work right. The Java Concurrency API came to the rescue. The charting data could be kicked off using CountDownLatch to ensure that we didn't start generating a new chart until the last chart was generated from the data. The sensor was generating more data than our application could chart in real-time.

In the last year, I have taught a couple of programming courses to our JUG, and invariably I need to cover Thread programming.

This is an example application that shows what happens if threads are left to their own devices. This example "works" sometimes, but usually the counter does not match up correctly with the other counters. You may need to run it a couple of times to "see" it break.

If you have a simple example that demonstrates this concept, please let me know. I am always looking for good ideas.

Here is the project code: ExecutorLatchExample

Executor.java


Runner.java


StaticCounter.java


Tuesday, November 13, 2012

JDK7 vs. JDK 6 File Monitoring

One of the really nice advancements, or features of Java 7 is the WatchService. This feature takes advantage of the OS file event notification facilities where available, or otherwise uses a "primitive" polling mechanism. In my blog article WatchService Using ScheduledExecutorService Example, I show an example of how to use the WatchService along with an ExecutorService to do file monitoring. This is really easy to implement and use.

However, the question of how to do it on JDK 6 was posed to me for those who can't do an upgrade for business reasons. I did a quick Google search to see what was out there. Alas, some of the most popular search results were poor, or really badly implemented solutions. I did come across a nice piece of code done by Pascal Essiembre. I didn't find much more on the developer. I would give a link to his work if I were sure that what I found was him. Pascal wrote the code below which is EPL 1.0 so you are free to use it. I used it to check it out, and it works likely in the same manner as the "primitive" implementation in JDK7. Here is the code unmodified from the form I found. This is very nicely done. Good code lives on. I just wish this were more near the top of the search results.

Thanks Pascal for your code contribution to the Java community.

Saturday, November 10, 2012

WatchService Using ScheduledExecutorService Example

I was developing some code for the Java Certification Boot Camp project on Java.net where I wanted to demonstrate how to use the WatchService from JDK7 to monitor filesystem activity. I also wanted to demonstrate using it with an Executor.

As part of the process, I needed a graceful way to exit the program when the program completed. I thought that I would simply Google a solution, but I did not find one that met my needs.

So here is the use case I would like to have a WatchService running in its own thread and monitoring the filesystem. After a time period, I would like the service to shutdown gracefully.

I decided to use A ScheduledExecutorService which would start the WatchService using a Callable<V>, and another Runnable which was scheduled to shutdown the WatchService and the ScheduledExecutorService.

So here is how I did it.

WatchServiceImpl.java


Wednesday, February 08, 2012

Book Review: Murach's Java Programming 4th Ed.

I recently had the pleasure to read and examine Murach's Java Programming 4th Ed. Joel Murach does a good job of producing training and reference manuals for a variety of Java technologies. This is no exception.

The book focuses on Java 7 Standard Edition, but does include a number of other features which were added in Java 5 and Java 6 for completeness.

One of the things I really like is that it uses NetBeans as the IDE to teach Java to the next generation of programmers. A lot of books on Java focus on the language itself. This would have the appearance that an IDE plays no role in learning Java. Any professional programmer will tell you that an IDE is absolutely essential in making you more productive. Joel's choice of NetBeans as a tool to teach Java with demonstrates its ease of use with beginners. Chapter 1 is dedicated to getting the new programmer up to speed with NetBeans.

The book offers educators and trainers optional support materials for teaching. This thoughtful approach to education is vital for anyone teaching Java.

The layout and examples are designed to get the programmer up to speed on the topic being covered.  A typical example of the layout is to have textual material on the left-side page with examples on the right. This allows you to read the material, and refer to the actual code examples. The book layout makes it easy to teach and learn. You are not left reading a volume of material without any code examples to make the essential points. This is a real benefit to the reader.

In addition, the book is developed with exercises to get the beginner involved. The exercises are based on the material learned in the chapter. The example exercises follow a common theme throughout the book allowing you to build on top of the information learned in the previous chapters. This common thread keeps you engaged through the book to see how the different topics tie the applications together.

Overall I would highly recommend the book to anyone looking to learn Java 7, or update their skills. I would give it (4/5) stars.

Chapters

Chapter 3 has a great section on using BigDecimal and arbitrary precision arithmetic. I really liked the explanation and examples. Although BigDecimal was added in 1.4.2 it is not used as much as it should, and this gives it a little press.

Chapter 5 mentions a best practice which is often overlooked. The practice is to add any custom exceptions to the package in which classes are likely to throw them. Often I find that the exceptions are in a package.exception package. This may be a good design if there is a general hierarchy for using the exceptions in multiple sub-packages, but generally is not the case.

Chapter 7 describes a relationship between a class and its instance. The description is eloquent and worth repeating.
"Once an instance of a class is created, it has an identity (a unique address) and a state (the values that it holds). Although an object's state may change throughout a program, its identity never does."
This is a beautiful explanation of OO programming relationships between a class and instance.

Chapter 8 has a discussion on the use of final. The point to be made is that if you declare a class final, all of its methods automatically become final implicitly.

Chapter 10 on nested classes really does a good job of explaining the requirements and limitations of nested classes. There are a couple of exam type gems like an inner class can not contain any static methods, or variables, and a static class can only reside inside another class.

In chapter 11, there was a remark about using Arrays.sort(Object[]) to sort an array. It mentioned that the objects must implement the Comparable interface. I thought that it would "naturally order" without it. I was wrong. I validated that specific case. Even an old dog can learn new tricks.

Chapter 19 is the best tutorial on StAX I have seen. It is simple and easy to follow. After reading the chapter, I will go back and look at StAX when I need this kind of low level XML handling.

Chapter 20 covers Apache Derby (JavaDB). It does a good job of explaining the basics, and gives some implementation recommendations. My only gripe is that the author fell into the Oracle trap of claiming that it is not an enterprise capable database. This is simply not true as borne out from my own experience.

If there is a weakness in the book, it has to do with Chapter 22 on Threads. The chapter does not cover this important topic in enough details. It also does not mention the Java Concurrency Library which has been standard since JDK 6, and handles a lot of the issues with direct thread programming. This chapter should be updated.

Errata

Figure 2-5 Statements that mix int and double variables. The first example requires a cast to int.
int result9 = (int) invoiceTotal / invoiceCount;
Figure 9-1 Example 1 should reflect the current Java design principles. All methods of a public interface are public and abstract.
public interface Printable {
void print();
}
Figure 9-1 Description bullet #3 should read
A classs that implements an interface must provide an implementation for each method defined by the interface, or the class must be declared abstract.
Figure 10-8 Bullet #2 is incorrect. A nested class does not need to be enclosed in a public class of the same file name as the public class. For example X.java could contain the following code:
class P {

    Q q;

    P() {
        q = new Q();
    }

    public Q getQ() {
        return q;
    }

    class Q {

        void print() {
            System.out.println("I am inside P");
        }
    }
}

This will work without being in a public class.

Figure 12-2 Common Collection Classes.
The statement that a HashSet requires that classes to implement a hashcode is incorrect.

Chapter 12 (Page 384) 2nd Para. incorrectly states the two queue methods as push and pull. The pull method does not exist, and was likely supposed to be pop. There are actually three from the Queue<E> interface of note: offer(E e), peek(), and poll.

Friday, August 05, 2011

Book Review: Java: The Good Parts

I had an opportunity to read Java: The Good Parts by Jim Waldo which was included in my Java 7 Launch Party Kit. I was not sure what to expect from the book. I was pleasantly surprised to discover it is a really good book.

There are a number of great quotes in the book which I will keep handy when I need to find a good code quote. Especially great were quotes to use with junior engineers.

The book covers a lot of history about decisions made in the Java language in the beginning, and how those decisions have evolved over time. The historical design decisions are still relevant today, and in some cases make the evolution of the platform more difficult. The idea that we must be able to run 1.0 Java code is rooted deeply in the language. The decision has caused a lot of legacy designs and constructs to remain in the code. Arguably, good, or bad depending on implementer, or implementation.

I was very happy to have been given the opportunity to read the book, and would give it 4/5 stars. It is a guide for senior developers to help mentor junior developers, and provides junior developers with answers to questions about why something was done a certain way in Java.

Details

The book is divided into eleven chapters: Introduction, Type System, Exceptions, Packages, Garbage Collection, JVM, Javadoc, Collections, RMI and Object Serialization, Concurrency, and Developer Ecology. These are in the author's opinion some of "good" parts of Java.

The introduction is more of a list of credentials for the author, and why we should consider him a subject matter expert. Jim certainly has the credentials to cover the topic being part of the early team on Java at Sun.

Chapter Two - Type System

The Type System is our first introduction to why the author feels this is a good part. The explanation has some historical perspective and is backed up with code. The real gem for me occurs under the topic A Real Problem where Jim has an interesting and insightful set of remarks. Jim explains a change in the class loading mechanism that was a response to a potential security issue which was discovered early on in Applet security. The issue was sharing of static variables across applets in a shared VM space. The fix was to ensure each applet was loaded by its own class loader. Also the run time type of an object would now be determined by a combination of its compile time type, and the class loader.

This now means that there is a difference between the compile time type of an Object and its run time type. It usually does not matter if you are not loading objects over the network, or not using multiple class loaders. If you do so, there can be consequences which should be considered. This is a sage piece of advice.

As noted, you will not notice most of the time if the Object is loaded by a common class loader. If they are loaded by different class loaders you will get a message telling you that the declared type is not the same as the run time type and are incompatible even though the source indicates they are the same.

Chapter Three - Exceptions

This chapter covers exceptions and starts with a great quote:
Those who object to the exception mechanism either don't understand it, don't realize what it can do, or are simply lazy twits who don't care about writing reliable code.
This is a great quote. Sometimes you feel like it was a bad idea, but it forces you think about what your code could do. We think of code with rose tinted glasses, and this allows us to get some clarity.

There is another quote on page 34 about some code which is not abstracted, and checks for exceptions after every operation.

This is the mistake of a puppy programmer. When you encounter such code, you should correct the writer, perhaps by rolling up a newspaper and swatting the offender.
That is one to keep in your hip pocket for use later.

On page 36, Jim points out a common form of exception handling which I have seen far too often and should result in the aforementioned swatting with a paper.

} catch (Exception ignored) {
// Catch and swallow.
}

I have seen too much of this, but this pattern is common in a try, catch, finally where you are closing a resource. This changes with Java 7 and try with resources.

The closing part of the chapter refers to the Dark Side. The discussion is focused on the evil of RuntimeException and why developers should avoid it. If you have been doing any development over time you will come across code you have written and is now deployed which has an exception condition you did not anticipate. Usually it occurs where we may have been a little lax on unit testing, and had to meet a deadline. When it occurs, we will be tempted to make the exception a RuntimeException so that we don't have to change our method signature. That is the temptation of the Dark Side. This is summed up in the following quote:
... If you actually design your code to throw only subclasses of RuntimeException, then you have gone beyond simple evil. You have now become a corrupter of others, and should feel the appropriate shame and be subject to the appropriate ridicule. 
Enough said.

Chapter Four - Packages

I started laughing and remembering my early days as a Java programmer.  Page 41 has a quote on using the unnamed package (default).

The unnamed package is a form of namespace limbo where code written by confused, obstinate, or lazy programmers is placed until they evolve to a higher life form.
Following that witty comment is one of the best explanations on why you should not use wildcard imports. I will quote the author once again since the explanation is succinct.

The more general form of the import statement is quite popular, but should be avoided if you can. By importing more than you need, you are polluting the namespace of your own code, and make it more likely that you will clash with some name that is defined in the other package.

Later there is an important discussion on examining the quantity of imports in a class. The more classes that are imported from another namespace may indicate an interconnection between the class, and the other namespace. This may indicate a design flaw, increased complexity, or lack of abstraction.

Chapter Five - Garbage Collection

There is a great explanation on the use of references in Java as opposed to pointers in C/C++. The primary reason we use references is because of garbage collection. The explanation is really well done, and gives you insight really why this is such a good part of Java. I actually found this chapter very interesting, and the historical perspective on what decisions were made and how it works today make the chapter a must read.

Later there is a discussion on finalizers and why you should avoid them as a programmer. The basic point is that the finalize() method may never be called. If you rely on the finalizer to cleanup your code, you may leave your data in an inconsistent state.

Chapter Six - Java Virtual Machine

The JVM is probably the most important part of Java. Its design and flexibility have allowed us to use it for more than just Java. Today the JVM allows us to run languages like Ruby (JRuby), and Scala on the same VM as Java. It allows us to combine these languages in a new "ployglot" programming style. The chapter is a discussion of the great flexibility of the JVM.

Chapter Seven - Javadoc

At first I was not sure why the author felt this was one of the good parts of Java. After reading his discussion on the subject I have become convinced he is correct.

I think that the {@inheritDoc} tag requires special mention. This is particularly important if you have a class which is implementing an interface, or extending a class. If the documentation is complete on the interface, or parent class, this allows you to inherit the documentation and allows the developer to be more productive without having to copy the previous comments to their implementation. It also allows you to add additional comments to the existing comments.

The author makes a very good recommendation: write the documentation for your interfaces first. The implementation classes simply need to inherit them.

Finally, the author concludes that Javadoc comment review is just as important as code review. I agree generally with the author, but I have found that the code changes over time, and often the Javadocs do not. So I take a position to not believe the Javadocs per se, and choose to use the force and read the source.

Chapter Eight - Collections

If there is any reason to buy this book, this is it. The explanation of the Collections API is very complete, and the historical reasons for how it was constructed, and the evolution over time is a walk down memory lane. The discussion about parametrized types, and the evolution of generics in Collections is very interesting, and informative. I have a new found appreciation of the difficulty, and the decisions made on how to incorporate them.

Additional information can be found in Java Generics and Collections by Maurice Naftalin and Philip Wadler (O'Reilly & Associates).

Chapter Nine - Remote Method Invocation and Object Serialization

Here is where I depart with the author. Jim was involved with the development of RMI. His love for the technology is apparent. Without a doubt, it is a valuable technology, but it is often dealt with on a higher level of abstraction today. Most Java developers could not write an RMI application without taking a trip to Google.

If you are looking at RMI, the author recommends using a security manager. Here is his quote on why:

Because RMI makes use of the ability of the JVM to dynamically load code, and because you don't want to load code without the protection of a security manager, programs using RMI should always be run with a security manager.

Object serialization is an important part of Java development today. This is particularly true of applications which are running on an application container. I was surprised to discover something about serialization I had not considered before. When serializing an object, it makes an object graph of all the classes that are contained in the object so that when it is de-serialized, it matches state of the application as completely as possible. There are two key items to remember.

  1. If two Objects serialized have a reference to a third common Object, when the objects are de-serialized. There will be two Objects created which represent the common third object. This could result in strange errors.
  2. All static variables are reset to the default values on the de-serialized object. Static variables are considered transient by serialization.
The second issue is particularly interesting to web developers. Session objects must be Serializable. This means you must keep the fact that static variables can not be assumed to be consistent since they are transient.

Chapter Ten - Concurrency

This is a boon to Java and an Achilles Heel. The author talks about a simple implementation, but refers you to other resources for more details on the subject.

The best book which should be on all developer's bookshelves is: Java Concurrency in Practice by Brian Goetz (Addison-Wesley). It is a must have for anyone doing concurrent programming. Also consider Java Threads by Scott Oaks and Henry Wong. A good book too on the subject.

One interesting note is mentioning the Timer object to schedule Thread processing. I would go further and recommend that the reader look at the Java Concurrency API instead. If you need anything more sophisticated than basic scheduling, it is the only logical choice.

Atomic data types are mentioned along with an example. This is something that most programmers, I believe, forget about. These are thread-safe data types which should always be considered in concurrent programming. Thanks for the reminder, simple explanation, and example.

Chapter Eleven - Developer Ecology

This concluding chapter talks about the evolution of the ecosystem in which Java development occurs. The advancement in tooling available should be used to increase productivity, and cleanliness of the code. The author covers items like IDEs, and unit testing. This is a nice conclusion to the book.
Enhanced by Zemanta

Tuesday, May 31, 2011

How to exercise your Daemons - Callable, Future, and ExecutorService

Mac OS X logoImage via Wikipedia
In a previous post, I mentioned how to add a shutdown hook to your application. This is great for the case where you need to do some cleanup prior to exiting. The example below shows how to convert your class to work like a daemon on UNIX, or a service on Windows. I will not go into details on how to create a UNIX, or Windows service. I will provide a StartupItem example for Mac OS X, or a modern inetd plist for launchd.

In the example classes below, I create a value holder object, a Callable<ValueHolder>, a Future<ValueHolder>, an ExecutorService which uses a SingleThreadExecutor. The concurrency libraries are from java.util.concurrent which is based on the original work done by Doug Lea, et. al. These classes make doing Thread based programming much simpler.

Here are the relevant files for the application:
JavaDaemonExample.zip (NetBeans 7.0 project)
JavaDaemonStartupItem.zip (This is for OS X 10.4 or less. It will work on 10.5+, but is not preferred)
com.bluelotussoftware.examples.Daemon (This is the inetd plist for launchd 10.5+ preferred)

Before we get to the code, the Mac OS X daemon controls must be modified to match your environment.

The com.bluelotussoftware.examples.Daemon plist file needs to modified to point to the jar file to execute. This is for Leopard, and Snow Leopard.
  1. To install it, place it in the ~/Library/LaunchAgents directory.
  2. From a command prompt, type:
    launchctl load -w /Users/jyeary/Library/LaunchAgents/JavaDaemonStartupItem/com.bluelotussoftware.examples.Daemon
    This loads it.
  3. To execute from launchctl:
    root:$ launctl
    launchd% start com.bluelotussoftware.examples.Daemon
    launchd% list
    launchd% quit
    root:$

Alternatively, you can use the JavaDaemonStartupItem.
  1. Modify the JavaDaemonStartupItem script to match your environment.
  2. Place the files in the /Library/StartupItems directory.
  3. Change permissions:
    sudo chown -R root:wheel JavaDaemonStartupItem
  4. Execute the application using:
    sudo /sbin/SystemStarter start "Java Daemon Example"

This is the main code Example:

Daemon.java


/*
 * Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 * 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
 *
 *      http://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.
 */
/*
 * $Id: Daemon.java 355 2011-05-31 21:05:01Z jyeary $
 */
package com.bluelotussoftware.examples;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Main executable daemon class.
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
public class Daemon {

    private static final Logger logger = Logger.getLogger(Daemon.class.getName());


    /**
     * Default no-argument constructor.
     */
    public Daemon() {

    }

    /**
     * Main execution entry point.
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        try {
            /* Create a file handler which is used to log output. This
             * becomes vitally important since we close the System.out,
             * System.err, and System.in streams next.
             */
            Handler handler = new FileHandler(Daemon.class.getName() + ".log");
            logger.addHandler(handler);
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
        } catch (SecurityException ex) {
            ex.printStackTrace(System.err);
        }

        logger.log(Level.INFO, "Closing streams");
        closeDefaultStreams();
        logger.log(Level.INFO, "Fetching ExecutorService");
        final ExecutorService executorService = Executors.newSingleThreadExecutor();
        logger.log(Level.INFO, "Adding Shutdown Hook");
        Runtime.getRuntime().addShutdownHook(new Thread() {

            @Override
            public void run() {
                shutdown(executorService);
            }
        });

        logger.log(Level.INFO, "Submitting CallableDaemon");
        Future<ValueHolder> future = executorService.submit(new CallableDaemon());
        logger.log(Level.INFO, "Waiting for results...");

        try {
            StringBuilder sb = new StringBuilder();
            sb.append("Results: ");
            sb.append(Arrays.toString(future.get().getDates().toArray()));
            logger.log(Level.INFO, sb.toString());
        } catch (InterruptedException ex) {
            logger.log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
        logger.log(Level.INFO, "Shutting down ExecutorService normally.");
        /* Call to shutdown executor service, otherwise the application blocks
         * and waits for another Runnable to be submitted. You can verify this in the
         * debugger, or by submitting another Runnable.
         */
        executorService.shutdown();
    }

    //TODO Need to verify that this is necessary for Windows systems.
    /**
     * This method closes {@code System#out}, {@code System#err}, and {@code System#in}
     * streams. This prevents premature shutdown from closure of terminal.
     */
    private static void closeDefaultStreams() {
        System.out.close();
        System.err.close();
        try {
            System.in.close();
        } catch (IOException ex) {
            logger.log(Level.WARNING, "Closing System.in() caused an Exception", ex);
        }
    }

    /**
     * Shutdown hook which calls {@code java.util.concurrent.ExecutorService#shutdownNow()}
     * @param executorService the executor which we want to attach to, and shutdown.
     */
    private static void shutdown(ExecutorService executorService) {
        logger.log(Level.INFO, "Executing shutdown hook");
        List<Runnable> runnables = executorService.shutdownNow();
        logger.log(Level.INFO, "The following items were awaiting execution when the daemon shutdown",
                Arrays.toString(runnables.toArray(new Runnable[runnables.size()])));
    }
}

This is the Callable<ValueHolder>:

CallableDaemon.java


/*
 * Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 * 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
 *
 *      http://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.
 */
/*
 * $Id: CallableDaemon.java 355 2011-05-31 21:05:01Z jyeary $
 */
package com.bluelotussoftware.examples;

import java.util.Date;
import java.util.concurrent.Callable;

/**
 * An example <code>Callable</code> implementation which executes and
 * waits. Every execution adds a <code>Date</code> to a <code>ValueHolder</code>.
 * On <code>call</code> completion, it returns the <code>ValueHolder</code>.
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
public class CallableDaemon implements Callable<ValueHolder> {

    private int counter;
    private int iterations = 12;

    /**
     * Default no-argument constructor.
     */
    public CallableDaemon() {
    }

    /**
     * Constructor which sets the number of iterations.
     * @param iterations integral value which sets the number
     * of iterations to be executed.
     */
    public CallableDaemon(int iterations) {
        this.iterations = iterations;
    }

    /**
     * {@inheritDoc java.util.concurrent.Callable#call()}
     */
    @Override
    public ValueHolder call() throws Exception {
        ValueHolder valueHolder = new ValueHolder();
        for (; counter < iterations; counter++) {
            valueHolder.getDates().add(new Date());
            synchronized (this) {
                this.wait(5000);
            }
        }
        return valueHolder;
    }
}

ValueHolder


/*
 * Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 * 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
 *
 *      http://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.
 */
/*
 * $Id: ValueHolder.java 355 2011-05-31 21:05:01Z jyeary $
 */
package com.bluelotussoftware.examples;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * A value holder object.
 * @author John Yeary <jyeary@bluelotussoftware.com>
 */
public class ValueHolder {

    private List<Date> dates;

    /**
     * Default no-argument constructor.
     */
    public ValueHolder() {
        dates = new ArrayList<Date>();
    }

    /**
     * Returns a {@code List<Date>} objects contained in the <code>ValueHolder</code>.
     * The method is synchronized because it can be used to add values to the internal
     * <code>List</code>.
     * @return {@code List<Date>} objects contained in the <code>ValueHolder</code>.
     */
    public synchronized List<Date> getDates() {
        return dates;
    }
}


Enhanced by Zemanta

Popular Posts