Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Java 9 Concurrency Cookbook, Second Edition

You're reading from   Java 9 Concurrency Cookbook, Second Edition Build highly scalable, robust, and concurrent applications

Arrow left icon
Product type Paperback
Published in Apr 2017
Publisher Packt
ISBN-13 9781787124417
Length 594 pages
Edition 2nd Edition
Languages
Concepts
Arrow right icon
Author (1):
Arrow left icon
Javier Fernández González Javier Fernández González
Author Profile Icon Javier Fernández González
Javier Fernández González
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

Preface 1. Thread Management FREE CHAPTER 2. Basic Thread Synchronization 3. Thread Synchronization Utilities 4. Thread Executors 5. Fork/Join Framework 6. Parallel and Reactive Streams 7. Concurrent Collections 8. Customizing Concurrency Classes 9. Testing Concurrent Applications 10. Additional Information 11. Concurrent Programming Design

Creating and running a daemon thread

Java has a special kind of thread called daemon thread. When daemon threads are the only threads running in a program, the JVM ends the program after finishing these threads.

With these characteristics, daemon threads are normally used as service providers for normal (also called user) threads running in the same program. They usually have an infinite loop that waits for the service request or performs the tasks of a thread. A typical example of these kinds of threads is the Java garbage collector.

In this recipe, we will learn how to create a daemon thread by developing an example with two threads: one user thread that would write events on a queue and a daemon thread that would clean the queue, removing the events that were generated more than 10 seconds ago.

Getting ready

The example for this recipe has been implemented using the Eclipse IDE. If you use Eclipse or a different IDE, such as NetBeans, open it and create a new Java project.

How to do it...

Follow these steps to implement the example:

  1. Create the Event class. This class only stores information about the events our program will work with. Declare two private attributes: one called the date of the java.util.Date type and the other called the event of the String type. Generate the methods to write and read their values.
  2. Create the WriterTask class and specify that it implements the Runnable interface:
        public class WriterTask implements Runnable {
  1. Declare the queue that stores the events and implement the constructor of the class that initializes this queue:
        private Deque<Event> deque; 
public WriterTask (Deque<Event> deque){
this.deque=deque;
}
  1. Implement the run() method of this task. This method will have a loop with 100 iterations. In each iteration, we create a new event, save it in the queue, and sleep for 1 second:
        @Override 
public void run() {
for (int i=1; i<100; i++) {
Event event=new Event();
event.setDate(new Date());
event.setEvent(String.format("The thread %s has generated
an event", Thread.currentThread().getId()));
deque.addFirst(event);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
  1. Create the CleanerTask class and specify that it extends the Thread class:
        public class CleanerTask extends Thread {
  1. Declare the queue that stores the events and implement the constructor of the class that initializes this queue. In the constructor, mark this thread as a daemon thread with the setDaemon() method:
        private Deque<Event> deque; 
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(true);
}
  1. Implement the run() method. It has an infinite loop that gets the actual date and calls the clean() method:
        @Override 
public void run() {
while (true) {
Date date = new Date();
clean(date);
}
}
  1. Implement the clean() method. It gets the last event, and if it was created more than 10 seconds ago, it deletes it and checks the next event. If an event is deleted, it writes the message of the event and the new size of the queue so you can see its evolution:
        private void clean(Date date) { 
long difference;
boolean delete;

if (deque.size()==0) {
return;
}
delete=false;
do {
Event e = deque.getLast();
difference = date.getTime() - e.getDate().getTime();
if (difference > 10000) {
System.out.printf("Cleaner: %s\n",e.getEvent());
deque.removeLast();
delete=true;
}
} while (difference > 10000);
if (delete){
System.out.printf("Cleaner: Size of the queue: %d\n",
deque.size());
}
}
  1. Now implement the main class. Create a class called Main with a main() method:
        public class Main { 
public static void main(String[] args) {
  1. Create the queue to store the events using the Deque class:
        Deque<Event> deque=new ConcurrentLinkedDeque<Event>();
  1. Create and start as many WriterTask threads as available processors have the JVM and one CleanerTask method:
        WriterTask writer=new WriterTask(deque); 
for (int i=0; i< Runtime.getRuntime().availableProcessors();
i++){
Thread thread=new Thread(writer);
thread.start();
}
CleanerTask cleaner=new CleanerTask(deque);
cleaner.start();
  1. Run the program and see the results.

How it works...

If you analyze the output of one execution of the program, you would see how the queue begins to grow until it has a size of, in our case, 40 events. Then, its size will vary around 40 events it has grown up to until the end of the execution. This size may depend on the number of cores of your machine. I have executed the code in a four-core processor, so we launch four WriterTask tasks.

The program starts with four WriterTask threads. Each thread writes an event and sleeps for 1 second. After the first 10 seconds, we have 40 events in the queue. During these 10 seconds, CleanerTask are executed whereas the four WriterTask threads sleep; however, but it doesn't delete any event because all of them were generated less than 10 seconds ago. During the rest of the execution, CleanerTask deletes four events every second and the four WriterTask threads write another four; therefore, the size of the queue varies around 40 events it has grown up to. Remember that the execution of this example depends on the number of available cores to the JVM of your computer. Normally, this number is equal to the number of cores of your CPU.

You can play with time until the WriterTask threads are sleeping. If you use a smaller value, you will see that CleanerTask has less CPU time and the size of the queue will increase because CleanerTask doesn't delete any event.

There's more...

You only can call the setDaemon() method before you call the start() method. Once the thread is running, you can't modify its daemon status calling the setDaemon() method. If you call it, you will get an IllegalThreadStateException exception.

You can use the isDaemon() method to check whether a thread is a daemon thread (the method returns true) or a non-daemon thread (the method returns false).

You have been reading a chapter from
Java 9 Concurrency Cookbook, Second Edition - Second Edition
Published in: Apr 2017
Publisher: Packt
ISBN-13: 9781787124417
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime