Skip to content

Commit c4eb198

Browse files
authored
Upload code files
1 parent 7067d1a commit c4eb198

File tree

4 files changed

+380
-0
lines changed

4 files changed

+380
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2016 Thomas Bauer
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.tls;
25+
26+
import java.util.ArrayList;
27+
import java.util.Calendar;
28+
import java.util.Collections;
29+
import java.util.Date;
30+
import java.util.List;
31+
32+
/**
33+
* ThreadLocal pattern
34+
* <p>
35+
* This App shows how to create an isolated space per each thread. In this
36+
* example the usage of SimpleDateFormat is made to be thread-safe. This is an
37+
* example of the ThreadLocal pattern.
38+
* <p>
39+
* By applying the ThreadLocal pattern you can keep track of application
40+
* instances or locale settings throughout the handling of a request. The
41+
* ThreadLocal class works like a static variable, with the exception that it is
42+
* only bound to the current thread! This allows us to use static variables in a
43+
* thread-safe way.
44+
* <p>
45+
* In Java, thread-local variables are implemented by the ThreadLocal class
46+
* object. ThreadLocal holds variable of type T, which is accessible via get/set
47+
* methods.
48+
* <p>
49+
* SimpleDateFormat is one of the basic Java classes and is not thread-safe. If
50+
* you do not isolate the instance of SimpleDateFormat per each thread then
51+
* problems arise. These problems are described with the example {@link AppUgly}
52+
*
53+
*/
54+
public class App {
55+
// A list to collect the date values created in the the threads
56+
static List<Date> dateList = Collections.synchronizedList(new ArrayList<Date>());
57+
58+
// A list to collect Exceptions thrown in the threads (should be none in
59+
// this example)
60+
static List<String> exceptionList = Collections.synchronizedList(new ArrayList<String>());
61+
62+
/**
63+
* Program entry point
64+
*
65+
* @param args
66+
* command line args
67+
*/
68+
public static void main(String[] args) {
69+
int counterDateValues = 0;
70+
int counterExceptions = 0;
71+
72+
// Create a runnable
73+
DateFormatRunnable runnableDf = new DateFormatRunnable("dd/MM/yyyy", "15/12/2015");
74+
// start 4 threads, each using the same Runnable instance
75+
Thread t1 = new Thread(runnableDf);
76+
Thread t2 = new Thread(runnableDf);
77+
Thread t3 = new Thread(runnableDf);
78+
Thread t4 = new Thread(runnableDf);
79+
t1.start();
80+
t2.start();
81+
t3.start();
82+
t4.start();
83+
try {
84+
t1.join();
85+
t2.join();
86+
t3.join();
87+
t4.join();
88+
} catch (InterruptedException e) {
89+
// Action not coded here
90+
}
91+
for (Date dt : dateList) {
92+
// a correct run should deliver 20 times 15.12.2015
93+
counterDateValues++;
94+
Calendar cal = Calendar.getInstance();
95+
cal.setTime(dt);
96+
// Formatted output of the date value: DD.MM.YYYY
97+
System.out.println(
98+
cal.get(Calendar.DAY_OF_MONTH) + "." + cal.get(Calendar.MONTH) + "." + +cal.get(Calendar.YEAR));
99+
}
100+
for (String ex : exceptionList) {
101+
// a correct run shouldn't deliver any exception
102+
counterExceptions++;
103+
System.out.println(ex);
104+
}
105+
System.out.println("The List dateList contains " + counterDateValues + " date values");
106+
System.out.println("The List exceptionList contains " + counterExceptions + " exceptions");
107+
}
108+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2016 Thomas Bauer
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.tls;
25+
26+
import java.util.ArrayList;
27+
import java.util.Calendar;
28+
import java.util.Collections;
29+
import java.util.Date;
30+
import java.util.List;
31+
32+
/**
33+
*
34+
* This App shows an example for problems with global thread variables. A global
35+
* thread variable is a variable defined as class variable of a
36+
* XyzRunnable-Class. In this example in the class
37+
* {@link DateFormatUglyRunnable}
38+
* <p>
39+
* Example use case: A well known problem with threads are non thread-safe Java
40+
* classes. One example is the class SimpleDateFormat.
41+
* <p>
42+
* In the example an instance of SimpleDateFormat is created in the constructor
43+
* of the Runnable. The constructor initializes a class variable with the
44+
* instance. The Runnable only does convert a string date to a date format using
45+
* the instance of SimpleDateFormat. It does this 5 times.
46+
* <p>
47+
* In the example 4 threads are started to do the same. If you are lucky
48+
* everything works well. But if you try more often you will happen to see
49+
* Exceptions. And these Exceptions arise on arbitrary points of the run.
50+
* <p>
51+
* The reason for this exceptions is: The threads try to use internal instance
52+
* variables of the SimpleDateFormat instance at the same time (the date is
53+
* stored internal as member variable during parsing and may be overwritten by
54+
* another thread during a parse is still running)
55+
* <p>
56+
* And even without Exceptions the run may not deliver the correct results.
57+
* All date values should be the same after the run. Check it
58+
*
59+
*/
60+
public class AppUgly {
61+
// A list to collect the date values created in the the threads
62+
static List<Date> dateList = Collections.synchronizedList(new ArrayList<Date>());
63+
// A list to collect Exceptions thrown in the threads
64+
static List<String> exceptionList = Collections.synchronizedList(new ArrayList<String>());
65+
66+
/**
67+
* Program entry point
68+
*
69+
* @param args
70+
* command line args
71+
*/
72+
public static void main(String[] args) {
73+
int counterDateValues = 0;
74+
int counterExceptions = 0;
75+
76+
// Prepare the Runnable
77+
DateFormatUglyRunnable runnableDf = new DateFormatUglyRunnable("dd/MM/yyyy", "15/12/2015");
78+
79+
// 4 threads using the same Runnable
80+
Thread t1 = new Thread(runnableDf);
81+
Thread t2 = new Thread(runnableDf);
82+
Thread t3 = new Thread(runnableDf);
83+
Thread t4 = new Thread(runnableDf);
84+
t1.start();
85+
t2.start();
86+
t3.start();
87+
t4.start();
88+
try {
89+
t1.join();
90+
t2.join();
91+
t3.join();
92+
t4.join();
93+
} catch (InterruptedException e) {
94+
// Action not coded here
95+
}
96+
for (Date dt : dateList) {
97+
// a correct run should deliver 20 times 15.12.2015
98+
counterDateValues++;
99+
Calendar cal = Calendar.getInstance();
100+
cal.setTime(dt);
101+
// Formatted output of the date value: DD.MM.YYYY
102+
System.out.println(cal.get(Calendar.DAY_OF_MONTH) + "." + cal.get(Calendar.MONTH) + "." + cal.get(Calendar.YEAR));
103+
}
104+
for (String ex : exceptionList) {
105+
// a correct run shouldn't deliver any exception
106+
counterExceptions++;
107+
System.out.println(ex);
108+
}
109+
System.out.println("The List dateList contains " + counterDateValues + " date values");
110+
System.out.println("The List exceptionList contains " + counterExceptions + " exceptions");
111+
}
112+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2016 Thomas Bauer
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.tls;
25+
26+
import java.text.DateFormat;
27+
import java.text.SimpleDateFormat;
28+
29+
/**
30+
* DateFormatRunnable converts string dates to a date format using
31+
* SimpleDateFormat The date format and the date value will be passed to the
32+
* Runnable by the constructor. The constructor creates a instance of
33+
* SimpleDateFormat and stores it in a ThreadLocal class variable. For the
34+
* complete description of the example see {@link App}
35+
*
36+
*/
37+
public class DateFormatRunnable implements Runnable {
38+
// class variables (members)
39+
private ThreadLocal<DateFormat> df;
40+
private String dateValue; // for date Value Thread Local not needed
41+
42+
/**
43+
* The date format and the date value are passed to the constructor
44+
*
45+
* @param inDateFormat
46+
* string date format string, e.g. "dd/MM/yyyy"
47+
* @param inDateValue
48+
* string date value, e.g. "21/06/2016"
49+
*/
50+
public DateFormatRunnable(String inDateFormat, String inDateValue) {
51+
final String idf = inDateFormat;
52+
this.df = new ThreadLocal<DateFormat>() {
53+
@Override
54+
protected DateFormat initialValue() {
55+
return new SimpleDateFormat(idf);
56+
}
57+
};
58+
this.dateValue = inDateValue;
59+
}
60+
61+
/**
62+
* @see java.lang.Runnable#run()
63+
*/
64+
@Override
65+
public void run() {
66+
System.out.println(Thread.currentThread() + " started executing...");
67+
68+
// Convert date value to date 5 times
69+
for (int i = 1; i <= 5; i++) {
70+
try {
71+
// this is the statement where it is important to have the
72+
// instance of SimpleDateFormat locally
73+
// Create the date value and store it in dateList
74+
App.dateList.add(this.df.get().parse(this.dateValue));
75+
} catch (Exception e) {
76+
// write the Exception to a list and continue work
77+
App.exceptionList.add(e.getClass() + ": " + e.getMessage());
78+
}
79+
80+
}
81+
82+
System.out.println(Thread.currentThread() + " finished executing");
83+
}
84+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2016 Thomas Bauer
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.tls;
25+
26+
import java.text.DateFormat;
27+
import java.text.SimpleDateFormat;
28+
29+
/**
30+
* DateFormatUglyRunnable converts string dates to a date format using
31+
* SimpleDateFormat. The date value and the date format will be passed to the
32+
* Runnable by the constructor. The constructor creates an instance of
33+
* SimpleDateFormat and stores it in a class variable. For the complete
34+
* description of the example see {@link AppUgly}
35+
*
36+
*/
37+
public class DateFormatUglyRunnable implements Runnable {
38+
// class variables (members)
39+
private DateFormat df;
40+
private String dateValue;
41+
42+
/**
43+
* The date format and the date value are passed to the constructor
44+
*
45+
* @param inDateFormat
46+
* string date format string, e.g. "dd/MM/yyyy"
47+
* @param inDateValue
48+
* string date value, e.g. "21/06/2016"
49+
*/
50+
public DateFormatUglyRunnable(String inDateFormat, String inDateValue) {
51+
this.df = new SimpleDateFormat(inDateFormat);
52+
this.dateValue = inDateValue;
53+
}
54+
55+
/**
56+
* @see java.lang.Runnable#run()
57+
*/
58+
@Override
59+
public void run() {
60+
System.out.println(Thread.currentThread() + " started executing...");
61+
62+
// Convert date value to date 5 times
63+
for (int i = 1; i <= 5; i++) {
64+
try {
65+
// Create the date value and store it in dateList
66+
AppUgly.dateList.add(this.df.parse(this.dateValue));
67+
} catch (Exception e) {
68+
// write the Exception to a list and continue work
69+
AppUgly.exceptionList.add(e.getClass() + ": " + e.getMessage());
70+
}
71+
72+
}
73+
74+
System.out.println(Thread.currentThread() + " finished executing");
75+
}
76+
}

0 commit comments

Comments
 (0)