格式化代码

This commit is contained in:
2018-06-17 20:31:19 +08:00
parent c47f63d484
commit d089585f2c
851 changed files with 32567 additions and 26715 deletions

View File

@@ -111,7 +111,7 @@
<!--Should BigEgg$Yolk be a _static_ inner class?--> <!--Should BigEgg$Yolk be a _static_ inner class?-->
<!--Should Egg$Yolk be a _static_ inner class?--> <!--Should Egg$Yolk be a _static_ inner class?-->
</Match> </Match>
<!-------- Checked to here -------------------------------------------------> <!-------- Checked to here ------------------------------------------------->
<Match class="Equivalence"> <Match class="Equivalence">
<BugCode name="RC"/> <BugCode name="RC"/>
<!--Suspicious comparison of java.lang.Integer references in Equivalence.main(String[]) At Equivalence.java:[line 7]--> <!--Suspicious comparison of java.lang.Integer references in Equivalence.main(String[]) At Equivalence.java:[line 7]-->

View File

@@ -1,14 +1,17 @@
package access;//: access/ChocolateChip.java package access;//: access/ChocolateChip.java
// Can't use package-access member from another package. // Can't use package-access member from another package.
import access.dessert.*; import access.dessert.*;
public class ChocolateChip extends Cookie { public class ChocolateChip extends Cookie {
public ChocolateChip() { public ChocolateChip() {
System.out.println("ChocolateChip constructor"); System.out.println("ChocolateChip constructor");
} }
public void chomp() { public void chomp() {
//! bite(); // Can't access bite //! bite(); // Can't access bite
} }
public static void main(String[] args) { public static void main(String[] args) {
ChocolateChip x = new ChocolateChip(); ChocolateChip x = new ChocolateChip();
x.chomp(); x.chomp();

View File

@@ -1,11 +1,16 @@
package access;//: access/ChocolateChip2.java package access;//: access/ChocolateChip2.java
import access.cookie2.*; import access.cookie2.*;
public class ChocolateChip2 extends Cookie { public class ChocolateChip2 extends Cookie {
public ChocolateChip2() { public ChocolateChip2() {
System.out.println("ChocolateChip2 constructor"); System.out.println("ChocolateChip2 constructor");
} }
public void chomp() { bite(); } // Protected method
public void chomp() {
bite();
} // Protected method
public static void main(String[] args) { public static void main(String[] args) {
ChocolateChip2 x = new ChocolateChip2(); ChocolateChip2 x = new ChocolateChip2();
x.chomp(); x.chomp();

View File

@@ -1,5 +1,6 @@
package access;//: access/Dinner.java package access;//: access/Dinner.java
// Uses the library. // Uses the library.
import access.dessert.*; import access.dessert.*;
public class Dinner { public class Dinner {

View File

@@ -2,7 +2,9 @@ package access;//: access/IceCream.java
// Demonstrates "private" keyword. // Demonstrates "private" keyword.
class Sundae { class Sundae {
private Sundae() {} private Sundae() {
}
static Sundae makeASundae() { static Sundae makeASundae() {
return new Sundae(); return new Sundae();
} }

View File

@@ -1,4 +1,5 @@
package access;//: access/ImportedMyClass.java package access;//: access/ImportedMyClass.java
import access.mypackage.*; import access.mypackage.*;
public class ImportedMyClass { public class ImportedMyClass {

View File

@@ -1,5 +1,6 @@
package access;//: access/LibTest.java package access;//: access/LibTest.java
// Uses the library. // Uses the library.
import net.mindview.simple.*; import net.mindview.simple.*;
public class LibTest { public class LibTest {

View File

@@ -3,7 +3,9 @@ package access;//: access/Lunch.java
// effectively private with private constructors: // effectively private with private constructors:
class Soup1 { class Soup1 {
private Soup1() {} private Soup1() {
}
// (1) Allow creation via static method: // (1) Allow creation via static method:
public static Soup1 makeSoup() { public static Soup1 makeSoup() {
return new Soup1(); return new Soup1();
@@ -11,14 +13,19 @@ class Soup1 {
} }
class Soup2 { class Soup2 {
private Soup2() {} private Soup2() {
}
// (2) Create a static object and return a reference // (2) Create a static object and return a reference
// upon request.(The "Singleton" pattern): // upon request.(The "Singleton" pattern):
private static Soup2 ps1 = new Soup2(); private static Soup2 ps1 = new Soup2();
public static Soup2 access() { public static Soup2 access() {
return ps1; return ps1;
} }
public void f() {}
public void f() {
}
} }
// Only one public class allowed per file: // Only one public class allowed per file:
@@ -27,9 +34,11 @@ public class Lunch {
// Can't do this! Private constructor: // Can't do this! Private constructor:
//! Soup1 soup = new Soup1(); //! Soup1 soup = new Soup1();
} }
void testStatic() { void testStatic() {
Soup1 soup = Soup1.makeSoup(); Soup1 soup = Soup1.makeSoup();
} }
void testSingleton() { void testSingleton() {
Soup2.access().f(); Soup2.access().f();
} }

View File

@@ -2,11 +2,17 @@ package access;//: access/OrganizedByAccess.java
public class OrganizedByAccess { public class OrganizedByAccess {
public void pub1() { /* ... */ } public void pub1() { /* ... */ }
public void pub2() { /* ... */ } public void pub2() { /* ... */ }
public void pub3() { /* ... */ } public void pub3() { /* ... */ }
private void priv1() { /* ... */ } private void priv1() { /* ... */ }
private void priv2() { /* ... */ } private void priv2() { /* ... */ }
private void priv3() { /* ... */ } private void priv3() { /* ... */ }
private int i; private int i;
// ... // ...
} ///:~ } ///:~

View File

@@ -2,5 +2,7 @@ package access;//: access/Pie.java
// The other class. // The other class.
class Pie { class Pie {
void f() { System.out.println("Pie.f()"); } void f() {
System.out.println("Pie.f()");
}
} ///:~ } ///:~

View File

@@ -1,5 +1,6 @@
package access;//: access/PrintTest.java package access;//: access/PrintTest.java
// Uses the static printing methods in Print.java. // Uses the static printing methods in Print.java.
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class PrintTest { public class PrintTest {

View File

@@ -1,4 +1,5 @@
package access;//: access/SingleImport.java package access;//: access/SingleImport.java
import java.util.ArrayList; import java.util.ArrayList;
public class SingleImport { public class SingleImport {

View File

@@ -5,6 +5,7 @@ public class Cookie {
public Cookie() { public Cookie() {
System.out.println("Cookie constructor"); System.out.println("Cookie constructor");
} }
protected void bite() { protected void bite() {
System.out.println("bite"); System.out.println("bite");
} }

View File

@@ -6,5 +6,8 @@ public class Cookie {
public Cookie() { public Cookie() {
System.out.println("Cookie constructor"); System.out.println("Cookie constructor");
} }
void bite() { System.out.println("bite"); }
void bite() {
System.out.println("bite");
}
} ///:~ } ///:~

View File

@@ -1,18 +1,24 @@
//: annotations/AtUnitComposition.java //: annotations/AtUnitComposition.java
// Creating non-embedded tests. // Creating non-embedded tests.
package annotations; package annotations;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
public class AtUnitComposition { public class AtUnitComposition {
AtUnitExample1 testObject = new AtUnitExample1(); AtUnitExample1 testObject = new AtUnitExample1();
@Test boolean _methodOne() {
@Test
boolean _methodOne() {
return return
testObject.methodOne().equals("This is methodOne"); testObject.methodOne().equals("This is methodOne");
} }
@Test boolean _methodTwo() {
@Test
boolean _methodTwo() {
return testObject.methodTwo() == 2; return testObject.methodTwo() == 2;
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
OSExecute.command( OSExecute.command(
"java net.mindview.atunit.AtUnit AtUnitComposition"); "java net.mindview.atunit.AtUnit AtUnitComposition");

View File

@@ -1,5 +1,6 @@
//: annotations/AtUnitExample1.java //: annotations/AtUnitExample1.java
package annotations; package annotations;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
@@ -7,18 +8,38 @@ public class AtUnitExample1 {
public String methodOne() { public String methodOne() {
return "This is methodOne"; return "This is methodOne";
} }
public int methodTwo() { public int methodTwo() {
System.out.println("This is methodTwo"); System.out.println("This is methodTwo");
return 2; return 2;
} }
@Test boolean methodOneTest() {
@Test
boolean methodOneTest() {
return methodOne().equals("This is methodOne"); return methodOne().equals("This is methodOne");
} }
@Test boolean m2() { return methodTwo() == 2; }
@Test private boolean m3() { return true; } @Test
boolean m2() {
return methodTwo() == 2;
}
@Test
private boolean m3() {
return true;
}
// Shows output for failure: // Shows output for failure:
@Test boolean failureTest() { return false; } @Test
@Test boolean anotherDisappointment() { return false; } boolean failureTest() {
return false;
}
@Test
boolean anotherDisappointment() {
return false;
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
OSExecute.command( OSExecute.command(
"java net.mindview.atunit.AtUnit AtUnitExample1"); "java net.mindview.atunit.AtUnit AtUnitExample1");

View File

@@ -1,7 +1,9 @@
//: annotations/AtUnitExample2.java //: annotations/AtUnitExample2.java
// Assertions and exceptions can be used in @Tests. // Assertions and exceptions can be used in @Tests.
package annotations; package annotations;
import java.io.*; import java.io.*;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
@@ -9,24 +11,34 @@ public class AtUnitExample2 {
public String methodOne() { public String methodOne() {
return "This is methodOne"; return "This is methodOne";
} }
public int methodTwo() { public int methodTwo() {
System.out.println("This is methodTwo"); System.out.println("This is methodTwo");
return 2; return 2;
} }
@Test void assertExample() {
@Test
void assertExample() {
assert methodOne().equals("This is methodOne"); assert methodOne().equals("This is methodOne");
} }
@Test void assertFailureExample() {
assert 1 == 2: "What a surprise!"; @Test
void assertFailureExample() {
assert 1 == 2 : "What a surprise!";
} }
@Test void exceptionExample() throws IOException {
@Test
void exceptionExample() throws IOException {
new FileInputStream("nofile.txt"); // Throws new FileInputStream("nofile.txt"); // Throws
} }
@Test boolean assertAndReturn() {
@Test
boolean assertAndReturn() {
// Assertion with message: // Assertion with message:
assert methodTwo() == 2: "methodTwo must equal 2"; assert methodTwo() == 2 : "methodTwo must equal 2";
return methodOne().equals("This is methodOne"); return methodOne().equals("This is methodOne");
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
OSExecute.command( OSExecute.command(
"java net.mindview.atunit.AtUnit AtUnitExample2"); "java net.mindview.atunit.AtUnit AtUnitExample2");

View File

@@ -1,27 +1,49 @@
//: annotations/AtUnitExample3.java //: annotations/AtUnitExample3.java
package annotations; package annotations;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
public class AtUnitExample3 { public class AtUnitExample3 {
private int n; private int n;
public AtUnitExample3(int n) { this.n = n; }
public int getN() { return n; } public AtUnitExample3(int n) {
this.n = n;
}
public int getN() {
return n;
}
public String methodOne() { public String methodOne() {
return "This is methodOne"; return "This is methodOne";
} }
public int methodTwo() { public int methodTwo() {
System.out.println("This is methodTwo"); System.out.println("This is methodTwo");
return 2; return 2;
} }
@TestObjectCreate static AtUnitExample3 create() {
@TestObjectCreate
static AtUnitExample3 create() {
return new AtUnitExample3(47); return new AtUnitExample3(47);
} }
@Test boolean initialization() { return n == 47; }
@Test boolean methodOneTest() { @Test
boolean initialization() {
return n == 47;
}
@Test
boolean methodOneTest() {
return methodOne().equals("This is methodOne"); return methodOne().equals("This is methodOne");
} }
@Test boolean m2() { return methodTwo() == 2; }
@Test
boolean m2() {
return methodTwo() == 2;
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
OSExecute.command( OSExecute.command(
"java net.mindview.atunit.AtUnit AtUnitExample3"); "java net.mindview.atunit.AtUnit AtUnitExample3");

View File

@@ -1,8 +1,11 @@
//: annotations/AtUnitExample4.java //: annotations/AtUnitExample4.java
package annotations; package annotations;
import java.util.*; import java.util.*;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class AtUnitExample4 { public class AtUnitExample4 {
@@ -11,36 +14,51 @@ public class AtUnitExample4 {
"middle, and then thin again at the far end."; "middle, and then thin again at the far end.";
private String word; private String word;
private Random rand = new Random(); // Time-based seed private Random rand = new Random(); // Time-based seed
public AtUnitExample4(String word) { this.word = word; }
public String getWord() { return word; } public AtUnitExample4(String word) {
this.word = word;
}
public String getWord() {
return word;
}
public String scrambleWord() { public String scrambleWord() {
List<Character> chars = new ArrayList<Character>(); List<Character> chars = new ArrayList<Character>();
for(Character c : word.toCharArray()) { for (Character c : word.toCharArray()) {
chars.add(c); chars.add(c);
} }
Collections.shuffle(chars, rand); Collections.shuffle(chars, rand);
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
for(char ch : chars) { for (char ch : chars) {
result.append(ch); result.append(ch);
} }
return result.toString(); return result.toString();
} }
@TestProperty static List<String> input =
@TestProperty
static List<String> input =
Arrays.asList(theory.split(" ")); Arrays.asList(theory.split(" "));
@TestProperty @TestProperty
static Iterator<String> words = input.iterator(); static Iterator<String> words = input.iterator();
@TestObjectCreate static AtUnitExample4 create() {
if(words.hasNext()) { @TestObjectCreate
static AtUnitExample4 create() {
if (words.hasNext()) {
return new AtUnitExample4(words.next()); return new AtUnitExample4(words.next());
} else { } else {
return null; return null;
} }
} }
@Test boolean words() {
@Test
boolean words() {
print("'" + getWord() + "'"); print("'" + getWord() + "'");
return getWord().equals("are"); return getWord().equals("are");
} }
@Test boolean scramble1() {
@Test
boolean scramble1() {
// Change to a specific seed to get verifiable results: // Change to a specific seed to get verifiable results:
rand = new Random(47); rand = new Random(47);
print("'" + getWord() + "'"); print("'" + getWord() + "'");
@@ -48,13 +66,16 @@ public class AtUnitExample4 {
print(scrambled); print(scrambled);
return scrambled.equals("lAl"); return scrambled.equals("lAl");
} }
@Test boolean scramble2() {
@Test
boolean scramble2() {
rand = new Random(74); rand = new Random(74);
print("'" + getWord() + "'"); print("'" + getWord() + "'");
String scrambled = scrambleWord(); String scrambled = scrambleWord();
print(scrambled); print(scrambled);
return scrambled.equals("tsaeborornussu"); return scrambled.equals("tsaeborornussu");
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
System.out.println("starting"); System.out.println("starting");
OSExecute.command( OSExecute.command(

View File

@@ -1,41 +1,64 @@
//: annotations/AtUnitExample5.java //: annotations/AtUnitExample5.java
package annotations; package annotations;
import java.io.*; import java.io.*;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
public class AtUnitExample5 { public class AtUnitExample5 {
private String text; private String text;
public AtUnitExample5(String text) { this.text = text; }
public String toString() { return text; } public AtUnitExample5(String text) {
@TestProperty static PrintWriter output; this.text = text;
@TestProperty static int counter; }
@TestObjectCreate static AtUnitExample5 create() {
@Override
public String toString() {
return text;
}
@TestProperty
static PrintWriter output;
@TestProperty
static int counter;
@TestObjectCreate
static AtUnitExample5 create() {
String id = Integer.toString(counter++); String id = Integer.toString(counter++);
try { try {
output = new PrintWriter("Test" + id + ".txt"); output = new PrintWriter("Test" + id + ".txt");
} catch(IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return new AtUnitExample5(id); return new AtUnitExample5(id);
} }
@TestObjectCleanup static void
@TestObjectCleanup
static void
cleanup(AtUnitExample5 tobj) { cleanup(AtUnitExample5 tobj) {
System.out.println("Running cleanup"); System.out.println("Running cleanup");
output.close(); output.close();
} }
@Test boolean test1() {
@Test
boolean test1() {
output.print("test1"); output.print("test1");
return true; return true;
} }
@Test boolean test2() {
@Test
boolean test2() {
output.print("test2"); output.print("test2");
return true; return true;
} }
@Test boolean test3() {
@Test
boolean test3() {
output.print("test3"); output.print("test3");
return true; return true;
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
OSExecute.command( OSExecute.command(
"java net.mindview.atunit.AtUnit AtUnitExample5"); "java net.mindview.atunit.AtUnit AtUnitExample5");

View File

@@ -1,14 +1,21 @@
//: annotations/AtUnitExternalTest.java //: annotations/AtUnitExternalTest.java
// Creating non-embedded tests. // Creating non-embedded tests.
package annotations; package annotations;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
public class AtUnitExternalTest extends AtUnitExample1 { public class AtUnitExternalTest extends AtUnitExample1 {
@Test boolean _methodOne() { @Test
boolean _methodOne() {
return methodOne().equals("This is methodOne"); return methodOne().equals("This is methodOne");
} }
@Test boolean _methodTwo() { return methodTwo() == 2; }
@Test
boolean _methodTwo() {
return methodTwo() == 2;
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
OSExecute.command( OSExecute.command(
"java net.mindview.atunit.AtUnit AtUnitExternalTest"); "java net.mindview.atunit.AtUnit AtUnitExternalTest");

View File

@@ -1,6 +1,7 @@
//: annotations/ExtractInterface.java //: annotations/ExtractInterface.java
// APT-based annotation processing. // APT-based annotation processing.
package annotations; package annotations;
import java.lang.annotation.*; import java.lang.annotation.*;
@Target(ElementType.TYPE) @Target(ElementType.TYPE)

View File

@@ -1,23 +1,32 @@
//: annotations/HashSetTest.java //: annotations/HashSetTest.java
package annotations; package annotations;
import java.util.*; import java.util.*;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
public class HashSetTest { public class HashSetTest {
HashSet<String> testObject = new HashSet<String>(); HashSet<String> testObject = new HashSet<String>();
@Test void initialization() {
@Test
void initialization() {
assert testObject.isEmpty(); assert testObject.isEmpty();
} }
@Test void _contains() {
@Test
void _contains() {
testObject.add("one"); testObject.add("one");
assert testObject.contains("one"); assert testObject.contains("one");
} }
@Test void _remove() {
@Test
void _remove() {
testObject.add("one"); testObject.add("one");
testObject.remove("one"); testObject.remove("one");
assert testObject.isEmpty(); assert testObject.isEmpty();
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
OSExecute.command( OSExecute.command(
"java net.mindview.atunit.AtUnit HashSetTest"); "java net.mindview.atunit.AtUnit HashSetTest");

View File

@@ -4,8 +4,10 @@
// annotations.InterfaceExtractorProcessorFactory // annotations.InterfaceExtractorProcessorFactory
// Multiplier.java -s ../annotations} // Multiplier.java -s ../annotations}
package annotations; package annotations;
import com.sun.mirror.apt.*; import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.*; import com.sun.mirror.declaration.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
@@ -14,40 +16,44 @@ public class InterfaceExtractorProcessor
private final AnnotationProcessorEnvironment env; private final AnnotationProcessorEnvironment env;
private ArrayList<MethodDeclaration> interfaceMethods = private ArrayList<MethodDeclaration> interfaceMethods =
new ArrayList<MethodDeclaration>(); new ArrayList<MethodDeclaration>();
public InterfaceExtractorProcessor( public InterfaceExtractorProcessor(
AnnotationProcessorEnvironment env) { this.env = env; } AnnotationProcessorEnvironment env) {
this.env = env;
}
public void process() { public void process() {
for(TypeDeclaration typeDecl : for (TypeDeclaration typeDecl :
env.getSpecifiedTypeDeclarations()) { env.getSpecifiedTypeDeclarations()) {
ExtractInterface annot = ExtractInterface annot =
typeDecl.getAnnotation(ExtractInterface.class); typeDecl.getAnnotation(ExtractInterface.class);
if(annot == null) { if (annot == null) {
break; break;
} }
for(MethodDeclaration m : typeDecl.getMethods()) { for (MethodDeclaration m : typeDecl.getMethods()) {
if(m.getModifiers().contains(Modifier.PUBLIC) && if (m.getModifiers().contains(Modifier.PUBLIC) &&
!(m.getModifiers().contains(Modifier.STATIC))) { !(m.getModifiers().contains(Modifier.STATIC))) {
interfaceMethods.add(m); interfaceMethods.add(m);
} }
} }
if(interfaceMethods.size() > 0) { if (interfaceMethods.size() > 0) {
try { try {
PrintWriter writer = PrintWriter writer =
env.getFiler().createSourceFile(annot.value()); env.getFiler().createSourceFile(annot.value());
writer.println("package " + writer.println("package " +
typeDecl.getPackage().getQualifiedName() +";"); typeDecl.getPackage().getQualifiedName() + ";");
writer.println("public interface " + writer.println("public interface " +
annot.value() + " {"); annot.value() + " {");
for(MethodDeclaration m : interfaceMethods) { for (MethodDeclaration m : interfaceMethods) {
writer.print(" public "); writer.print(" public ");
writer.print(m.getReturnType() + " "); writer.print(m.getReturnType() + " ");
writer.print(m.getSimpleName() + " ("); writer.print(m.getSimpleName() + " (");
int i = 0; int i = 0;
for(ParameterDeclaration parm : for (ParameterDeclaration parm :
m.getParameters()) { m.getParameters()) {
writer.print(parm.getType() + " " + writer.print(parm.getType() + " " +
parm.getSimpleName()); parm.getSimpleName());
if(++i < m.getParameters().size()) { if (++i < m.getParameters().size()) {
writer.print(", "); writer.print(", ");
} }
} }
@@ -55,7 +61,7 @@ public class InterfaceExtractorProcessor
} }
writer.println("}"); writer.println("}");
writer.close(); writer.close();
} catch(IOException ioe) { } catch (IOException ioe) {
throw new RuntimeException(ioe); throw new RuntimeException(ioe);
} }
} }

View File

@@ -1,8 +1,10 @@
//: annotations/InterfaceExtractorProcessorFactory.java //: annotations/InterfaceExtractorProcessorFactory.java
// APT-based annotation processing. // APT-based annotation processing.
package annotations; package annotations;
import com.sun.mirror.apt.*; import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.*; import com.sun.mirror.declaration.*;
import java.util.*; import java.util.*;
public class InterfaceExtractorProcessorFactory public class InterfaceExtractorProcessorFactory
@@ -12,10 +14,12 @@ public class InterfaceExtractorProcessorFactory
AnnotationProcessorEnvironment env) { AnnotationProcessorEnvironment env) {
return new InterfaceExtractorProcessor(env); return new InterfaceExtractorProcessor(env);
} }
public Collection<String> supportedAnnotationTypes() { public Collection<String> supportedAnnotationTypes() {
return return
Collections.singleton("annotations.ExtractInterface"); Collections.singleton("annotations.ExtractInterface");
} }
public Collection<String> supportedOptions() { public Collection<String> supportedOptions() {
return Collections.emptySet(); return Collections.emptySet();
} }

View File

@@ -6,12 +6,16 @@ package annotations;
public class Multiplier { public class Multiplier {
public int multiply(int x, int y) { public int multiply(int x, int y) {
int total = 0; int total = 0;
for(int i = 0; i < x; i++) { for (int i = 0; i < x; i++) {
total = add(total, y); total = add(total, y);
} }
return total; return total;
} }
private int add(int x, int y) { return x + y; }
private int add(int x, int y) {
return x + y;
}
public static void main(String[] args) { public static void main(String[] args) {
Multiplier m = new Multiplier(); Multiplier m = new Multiplier();
System.out.println("11*16 = " + m.multiply(11, 16)); System.out.println("11*16 = " + m.multiply(11, 16));

View File

@@ -1,4 +1,5 @@
package annotations;//: annotations/PasswordUtils.java package annotations;//: annotations/PasswordUtils.java
import java.util.*; import java.util.*;
public class PasswordUtils { public class PasswordUtils {
@@ -7,10 +8,12 @@ public class PasswordUtils {
public boolean validatePassword(String password) { public boolean validatePassword(String password) {
return (password.matches("\\w*\\d\\w*")); return (password.matches("\\w*\\d\\w*"));
} }
@UseCase(id = 48) @UseCase(id = 48)
public String encryptPassword(String password) { public String encryptPassword(String password) {
return new StringBuilder(password).reverse().toString(); return new StringBuilder(password).reverse().toString();
} }
@UseCase(id = 49, description = @UseCase(id = 49, description =
"New passwords can't equal previously used ones") "New passwords can't equal previously used ones")
public boolean checkForNewPassword( public boolean checkForNewPassword(

View File

@@ -1,9 +1,11 @@
package annotations;//: annotations/SimulatingNull.java package annotations;//: annotations/SimulatingNull.java
import java.lang.annotation.*; import java.lang.annotation.*;
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface SimulatingNull { public @interface SimulatingNull {
public int id() default -1; public int id() default -1;
public String description() default ""; public String description() default "";
} ///:~ } ///:~

View File

@@ -1,11 +1,21 @@
//: annotations/StackL.java //: annotations/StackL.java
// A stack built on a linkedList. // A stack built on a linkedList.
package annotations; package annotations;
import java.util.*; import java.util.*;
public class StackL<T> { public class StackL<T> {
private LinkedList<T> list = new LinkedList<T>(); private LinkedList<T> list = new LinkedList<T>();
public void push(T v) { list.addFirst(v); }
public T top() { return list.getFirst(); } public void push(T v) {
public T pop() { return list.removeFirst(); } list.addFirst(v);
}
public T top() {
return list.getFirst();
}
public T pop() {
return list.removeFirst();
}
} ///:~ } ///:~

View File

@@ -1,28 +1,35 @@
//: annotations/StackLStringTest.java //: annotations/StackLStringTest.java
// Applying @Unit to generics. // Applying @Unit to generics.
package annotations; package annotations;
import net.mindview.atunit.*; import net.mindview.atunit.*;
import net.mindview.util.*; import net.mindview.util.*;
public class StackLStringTest extends StackL<String> { public class StackLStringTest extends StackL<String> {
@Test void _push() { @Test
void _push() {
push("one"); push("one");
assert top().equals("one"); assert top().equals("one");
push("two"); push("two");
assert top().equals("two"); assert top().equals("two");
} }
@Test void _pop() {
@Test
void _pop() {
push("one"); push("one");
push("two"); push("two");
assert pop().equals("two"); assert pop().equals("two");
assert pop().equals("one"); assert pop().equals("one");
} }
@Test void _top() {
@Test
void _top() {
push("A"); push("A");
push("B"); push("B");
assert top().equals("B"); assert top().equals("B");
assert top().equals("B"); assert top().equals("B");
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
OSExecute.command( OSExecute.command(
"java net.mindview.atunit.AtUnit StackLStringTest"); "java net.mindview.atunit.AtUnit StackLStringTest");

View File

@@ -1,10 +1,15 @@
//: annotations/Testable.java //: annotations/Testable.java
package annotations; package annotations;
import net.mindview.atunit.*; import net.mindview.atunit.*;
public class Testable { public class Testable {
public void execute() { public void execute() {
System.out.println("Executing.."); System.out.println("Executing..");
} }
@Test void testExecute() { execute(); }
@Test
void testExecute() {
execute();
}
} ///:~ } ///:~

View File

@@ -1,9 +1,11 @@
package annotations;//: annotations/UseCase.java package annotations;//: annotations/UseCase.java
import java.lang.annotation.*; import java.lang.annotation.*;
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface UseCase { public @interface UseCase {
public int id(); public int id();
public String description() default "no description"; public String description() default "no description";
} ///:~ } ///:~

View File

@@ -1,22 +1,24 @@
package annotations;//: annotations/UseCaseTracker.java package annotations;//: annotations/UseCaseTracker.java
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
public class UseCaseTracker { public class UseCaseTracker {
public static void public static void
trackUseCases(List<Integer> useCases, Class<?> cl) { trackUseCases(List<Integer> useCases, Class<?> cl) {
for(Method m : cl.getDeclaredMethods()) { for (Method m : cl.getDeclaredMethods()) {
UseCase uc = m.getAnnotation(UseCase.class); UseCase uc = m.getAnnotation(UseCase.class);
if(uc != null) { if (uc != null) {
System.out.println("Found Use Case:" + uc.id() + System.out.println("Found Use Case:" + uc.id() +
" " + uc.description()); " " + uc.description());
useCases.remove(new Integer(uc.id())); useCases.remove(new Integer(uc.id()));
} }
} }
for(int i : useCases) { for (int i : useCases) {
System.out.println("Warning: Missing use case-" + i); System.out.println("Warning: Missing use case-" + i);
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
List<Integer> useCases = new ArrayList<Integer>(); List<Integer> useCases = new ArrayList<Integer>();
Collections.addAll(useCases, 47, 48, 49, 50); Collections.addAll(useCases, 47, 48, 49, 50);

View File

@@ -1,11 +1,14 @@
//: annotations/database/Constraints.java //: annotations/database/Constraints.java
package annotations.database; package annotations.database;
import java.lang.annotation.*; import java.lang.annotation.*;
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Constraints { public @interface Constraints {
boolean primaryKey() default false; boolean primaryKey() default false;
boolean allowNull() default true; boolean allowNull() default true;
boolean unique() default false; boolean unique() default false;
} ///:~ } ///:~

View File

@@ -1,5 +1,6 @@
//: annotations/database/DBTable.java //: annotations/database/DBTable.java
package annotations.database; package annotations.database;
import java.lang.annotation.*; import java.lang.annotation.*;
@Target(ElementType.TYPE) // Applies to classes only @Target(ElementType.TYPE) // Applies to classes only

View File

@@ -3,16 +3,35 @@ package annotations.database;
@DBTable(name = "MEMBER") @DBTable(name = "MEMBER")
public class Member { public class Member {
@SQLString(30) String firstName; @SQLString(30)
@SQLString(50) String lastName; String firstName;
@SQLInteger Integer age; @SQLString(50)
String lastName;
@SQLInteger
Integer age;
@SQLString(value = 30, @SQLString(value = 30,
constraints = @Constraints(primaryKey = true)) constraints = @Constraints(primaryKey = true))
String handle; String handle;
static int memberCount; static int memberCount;
public String getHandle() { return handle; }
public String getFirstName() { return firstName; } public String getHandle() {
public String getLastName() { return lastName; } return handle;
public String toString() { return handle; } }
public Integer getAge() { return age; }
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@Override
public String toString() {
return handle;
}
public Integer getAge() {
return age;
}
} ///:~ } ///:~

View File

@@ -1,10 +1,12 @@
//: annotations/database/SQLInteger.java //: annotations/database/SQLInteger.java
package annotations.database; package annotations.database;
import java.lang.annotation.*; import java.lang.annotation.*;
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger { public @interface SQLInteger {
String name() default ""; String name() default "";
Constraints constraints() default @Constraints; Constraints constraints() default @Constraints;
} ///:~ } ///:~

View File

@@ -1,11 +1,14 @@
//: annotations/database/SQLString.java //: annotations/database/SQLString.java
package annotations.database; package annotations.database;
import java.lang.annotation.*; import java.lang.annotation.*;
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface SQLString { public @interface SQLString {
int value() default 0; int value() default 0;
String name() default ""; String name() default "";
Constraints constraints() default @Constraints; Constraints constraints() default @Constraints;
} ///:~ } ///:~

View File

@@ -4,10 +4,13 @@
// annotations.database.TableCreationProcessorFactory // annotations.database.TableCreationProcessorFactory
// database/Member.java -s database} // database/Member.java -s database}
package annotations.database; package annotations.database;
import com.sun.mirror.apt.*; import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.*; import com.sun.mirror.declaration.*;
import com.sun.mirror.util.*; import com.sun.mirror.util.*;
import java.util.*; import java.util.*;
import static com.sun.mirror.util.DeclarationVisitors.*; import static com.sun.mirror.util.DeclarationVisitors.*;
public class TableCreationProcessorFactory public class TableCreationProcessorFactory
@@ -17,6 +20,7 @@ public class TableCreationProcessorFactory
AnnotationProcessorEnvironment env) { AnnotationProcessorEnvironment env) {
return new TableCreationProcessor(env); return new TableCreationProcessor(env);
} }
public Collection<String> supportedAnnotationTypes() { public Collection<String> supportedAnnotationTypes() {
return Arrays.asList( return Arrays.asList(
"annotations.database.DBTable", "annotations.database.DBTable",
@@ -24,19 +28,23 @@ public class TableCreationProcessorFactory
"annotations.database.SQLString", "annotations.database.SQLString",
"annotations.database.SQLInteger"); "annotations.database.SQLInteger");
} }
public Collection<String> supportedOptions() { public Collection<String> supportedOptions() {
return Collections.emptySet(); return Collections.emptySet();
} }
private static class TableCreationProcessor private static class TableCreationProcessor
implements AnnotationProcessor { implements AnnotationProcessor {
private final AnnotationProcessorEnvironment env; private final AnnotationProcessorEnvironment env;
private String sql = ""; private String sql = "";
public TableCreationProcessor( public TableCreationProcessor(
AnnotationProcessorEnvironment env) { AnnotationProcessorEnvironment env) {
this.env = env; this.env = env;
} }
public void process() { public void process() {
for(TypeDeclaration typeDecl : for (TypeDeclaration typeDecl :
env.getSpecifiedTypeDeclarations()) { env.getSpecifiedTypeDeclarations()) {
typeDecl.accept(getDeclarationScanner( typeDecl.accept(getDeclarationScanner(
new TableCreationVisitor(), NO_OP)); new TableCreationVisitor(), NO_OP));
@@ -45,12 +53,13 @@ public class TableCreationProcessorFactory
sql = ""; sql = "";
} }
} }
private class TableCreationVisitor private class TableCreationVisitor
extends SimpleDeclarationVisitor { extends SimpleDeclarationVisitor {
public void visitClassDeclaration( public void visitClassDeclaration(
ClassDeclaration d) { ClassDeclaration d) {
DBTable dbTable = d.getAnnotation(DBTable.class); DBTable dbTable = d.getAnnotation(DBTable.class);
if(dbTable != null) { if (dbTable != null) {
sql += "CREATE TABLE "; sql += "CREATE TABLE ";
sql += (dbTable.name().length() < 1) sql += (dbTable.name().length() < 1)
? d.getSimpleName().toUpperCase() ? d.getSimpleName().toUpperCase()
@@ -58,14 +67,15 @@ public class TableCreationProcessorFactory
sql += " ("; sql += " (";
} }
} }
public void visitFieldDeclaration( public void visitFieldDeclaration(
FieldDeclaration d) { FieldDeclaration d) {
String columnName = ""; String columnName = "";
if(d.getAnnotation(SQLInteger.class) != null) { if (d.getAnnotation(SQLInteger.class) != null) {
SQLInteger sInt = d.getAnnotation( SQLInteger sInt = d.getAnnotation(
SQLInteger.class); SQLInteger.class);
// Use field name if name not specified // Use field name if name not specified
if(sInt.name().length() < 1) { if (sInt.name().length() < 1) {
columnName = d.getSimpleName().toUpperCase(); columnName = d.getSimpleName().toUpperCase();
} else { } else {
columnName = sInt.name(); columnName = sInt.name();
@@ -73,11 +83,11 @@ public class TableCreationProcessorFactory
sql += "\n " + columnName + " INT" + sql += "\n " + columnName + " INT" +
getConstraints(sInt.constraints()) + ","; getConstraints(sInt.constraints()) + ",";
} }
if(d.getAnnotation(SQLString.class) != null) { if (d.getAnnotation(SQLString.class) != null) {
SQLString sString = d.getAnnotation( SQLString sString = d.getAnnotation(
SQLString.class); SQLString.class);
// Use field name if name not specified. // Use field name if name not specified.
if(sString.name().length() < 1) { if (sString.name().length() < 1) {
columnName = d.getSimpleName().toUpperCase(); columnName = d.getSimpleName().toUpperCase();
} else { } else {
columnName = sString.name(); columnName = sString.name();
@@ -87,15 +97,16 @@ public class TableCreationProcessorFactory
getConstraints(sString.constraints()) + ","; getConstraints(sString.constraints()) + ",";
} }
} }
private String getConstraints(Constraints con) { private String getConstraints(Constraints con) {
String constraints = ""; String constraints = "";
if(!con.allowNull()) { if (!con.allowNull()) {
constraints += " NOT NULL"; constraints += " NOT NULL";
} }
if(con.primaryKey()) { if (con.primaryKey()) {
constraints += " PRIMARY KEY"; constraints += " PRIMARY KEY";
} }
if(con.unique()) { if (con.unique()) {
constraints += " UNIQUE"; constraints += " UNIQUE";
} }
return constraints; return constraints;

View File

@@ -2,40 +2,41 @@
// Reflection-based annotation processor. // Reflection-based annotation processor.
// {Args: annotations.database.Member} // {Args: annotations.database.Member}
package annotations.database; package annotations.database;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
public class TableCreator { public class TableCreator {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
if(args.length < 1) { if (args.length < 1) {
System.out.println("arguments: annotated classes"); System.out.println("arguments: annotated classes");
System.exit(0); System.exit(0);
} }
for(String className : args) { for (String className : args) {
Class<?> cl = Class.forName(className); Class<?> cl = Class.forName(className);
DBTable dbTable = cl.getAnnotation(DBTable.class); DBTable dbTable = cl.getAnnotation(DBTable.class);
if(dbTable == null) { if (dbTable == null) {
System.out.println( System.out.println(
"No DBTable annotations in class " + className); "No DBTable annotations in class " + className);
continue; continue;
} }
String tableName = dbTable.name(); String tableName = dbTable.name();
// If the name is empty, use the Class name: // If the name is empty, use the Class name:
if(tableName.length() < 1) { if (tableName.length() < 1) {
tableName = cl.getName().toUpperCase(); tableName = cl.getName().toUpperCase();
} }
List<String> columnDefs = new ArrayList<String>(); List<String> columnDefs = new ArrayList<String>();
for(Field field : cl.getDeclaredFields()) { for (Field field : cl.getDeclaredFields()) {
String columnName = null; String columnName = null;
Annotation[] anns = field.getDeclaredAnnotations(); Annotation[] anns = field.getDeclaredAnnotations();
if(anns.length < 1) { if (anns.length < 1) {
continue; // Not a db table column continue; // Not a db table column
} }
if(anns[0] instanceof SQLInteger) { if (anns[0] instanceof SQLInteger) {
SQLInteger sInt = (SQLInteger) anns[0]; SQLInteger sInt = (SQLInteger) anns[0];
// Use field name if name not specified // Use field name if name not specified
if(sInt.name().length() < 1) { if (sInt.name().length() < 1) {
columnName = field.getName().toUpperCase(); columnName = field.getName().toUpperCase();
} else { } else {
columnName = sInt.name(); columnName = sInt.name();
@@ -43,10 +44,10 @@ public class TableCreator {
columnDefs.add(columnName + " INT" + columnDefs.add(columnName + " INT" +
getConstraints(sInt.constraints())); getConstraints(sInt.constraints()));
} }
if(anns[0] instanceof SQLString) { if (anns[0] instanceof SQLString) {
SQLString sString = (SQLString) anns[0]; SQLString sString = (SQLString) anns[0];
// Use field name if name not specified. // Use field name if name not specified.
if(sString.name().length() < 1) { if (sString.name().length() < 1) {
columnName = field.getName().toUpperCase(); columnName = field.getName().toUpperCase();
} else { } else {
columnName = sString.name(); columnName = sString.name();
@@ -57,7 +58,7 @@ public class TableCreator {
} }
StringBuilder createCommand = new StringBuilder( StringBuilder createCommand = new StringBuilder(
"CREATE TABLE " + tableName + "("); "CREATE TABLE " + tableName + "(");
for(String columnDef : columnDefs) { for (String columnDef : columnDefs) {
createCommand.append("\n " + columnDef + ","); createCommand.append("\n " + columnDef + ",");
} }
// Remove trailing comma // Remove trailing comma
@@ -68,15 +69,16 @@ public class TableCreator {
} }
} }
} }
private static String getConstraints(Constraints con) { private static String getConstraints(Constraints con) {
String constraints = ""; String constraints = "";
if(!con.allowNull()) { if (!con.allowNull()) {
constraints += " NOT NULL"; constraints += " NOT NULL";
} }
if(con.primaryKey()) { if (con.primaryKey()) {
constraints += " PRIMARY KEY"; constraints += " PRIMARY KEY";
} }
if(con.unique()) { if (con.unique()) {
constraints += " UNIQUE"; constraints += " UNIQUE";
} }
return constraints; return constraints;

View File

@@ -4,5 +4,5 @@ package annotations.database;
public @interface Uniqueness { public @interface Uniqueness {
Constraints constraints() Constraints constraints()
default @Constraints(unique=true); default @Constraints(unique = true);
} ///:~ } ///:~

View File

@@ -1,6 +1,8 @@
package arrays;//: arrays/AlphabeticSearch.java package arrays;//: arrays/AlphabeticSearch.java
// Searching with a Comparator. // Searching with a Comparator.
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
public class AlphabeticSearch { public class AlphabeticSearch {
@@ -11,7 +13,7 @@ public class AlphabeticSearch {
System.out.println(Arrays.toString(sa)); System.out.println(Arrays.toString(sa));
int index = Arrays.binarySearch(sa, sa[10], int index = Arrays.binarySearch(sa, sa[10],
String.CASE_INSENSITIVE_ORDER); String.CASE_INSENSITIVE_ORDER);
System.out.println("Index: "+ index + "\n"+ sa[index]); System.out.println("Index: " + index + "\n" + sa[index]);
} }
} /* Output: } /* Output:
[bkIna, cQrGs, cXZJo, dLsmw, eGZMm, EqUCB, gwsqP, hKcxr, HLGEa, HqXum, HxxHv, JMRoE, JmzMs, Mesbt, MNvqe, nyGcF, ogoYW, OneOE, OWZnT, RFJQA, rUkZP, sgqia, slJrL, suEcU, uTpnX, vpfFv, WHkjU, xxEAJ, YNzbr, zDyCy] [bkIna, cQrGs, cXZJo, dLsmw, eGZMm, EqUCB, gwsqP, hKcxr, HLGEa, HqXum, HxxHv, JMRoE, JmzMs, Mesbt, MNvqe, nyGcF, ogoYW, OneOE, OWZnT, RFJQA, rUkZP, sgqia, slJrL, suEcU, uTpnX, vpfFv, WHkjU, xxEAJ, YNzbr, zDyCy]

View File

@@ -3,10 +3,11 @@ package arrays;//: arrays/ArrayOfGenericType.java
public class ArrayOfGenericType<T> { public class ArrayOfGenericType<T> {
T[] array; // OK T[] array; // OK
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public ArrayOfGenericType(int size) { public ArrayOfGenericType(int size) {
//! array = new T[size]; // Illegal //! array = new T[size]; // Illegal
array = (T[])new Object[size]; // "unchecked" Warning array = (T[]) new Object[size]; // "unchecked" Warning
} }
// Illegal: // Illegal:
//! public <U> U[] makeArray() { return new U[10]; } //! public <U> U[] makeArray() { return new U[10]; }

View File

@@ -1,5 +1,6 @@
package arrays;//: arrays/ArrayOfGenerics.java package arrays;//: arrays/ArrayOfGenerics.java
// It is possible to create arrays of generics. // It is possible to create arrays of generics.
import java.util.*; import java.util.*;
public class ArrayOfGenerics { public class ArrayOfGenerics {
@@ -7,7 +8,7 @@ public class ArrayOfGenerics {
public static void main(String[] args) { public static void main(String[] args) {
List<String>[] ls; List<String>[] ls;
List[] la = new List[10]; List[] la = new List[10];
ls = (List<String>[])la; // "Unchecked" warning ls = (List<String>[]) la; // "Unchecked" warning
ls[0] = new ArrayList<String>(); ls[0] = new ArrayList<String>();
// Compile-time checking produces an error: // Compile-time checking produces an error:
//! ls[1] = new ArrayList<Integer>(); //! ls[1] = new ArrayList<Integer>();
@@ -21,8 +22,8 @@ public class ArrayOfGenerics {
// possible to create an array of generics, albeit // possible to create an array of generics, albeit
// with an "unchecked" warning: // with an "unchecked" warning:
List<BerylliumSphere>[] spheres = List<BerylliumSphere>[] spheres =
(List<BerylliumSphere>[])new List[10]; (List<BerylliumSphere>[]) new List[10];
for(int i = 0; i < spheres.length; i++) { for (int i = 0; i < spheres.length; i++) {
spheres[i] = new ArrayList<BerylliumSphere>(); spheres[i] = new ArrayList<BerylliumSphere>();
} }
} }

View File

@@ -1,6 +1,8 @@
package arrays;//: arrays/ArrayOptions.java package arrays;//: arrays/ArrayOptions.java
// Initialization & re-assignment of arrays. // Initialization & re-assignment of arrays.
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class ArrayOptions { public class ArrayOptions {
@@ -12,14 +14,14 @@ public class ArrayOptions {
// automatically initialized to null: // automatically initialized to null:
print("b: " + Arrays.toString(b)); print("b: " + Arrays.toString(b));
BerylliumSphere[] c = new BerylliumSphere[4]; BerylliumSphere[] c = new BerylliumSphere[4];
for(int i = 0; i < c.length; i++) { for (int i = 0; i < c.length; i++) {
if(c[i] == null) // Can test for null reference if (c[i] == null) // Can test for null reference
{ {
c[i] = new BerylliumSphere(); c[i] = new BerylliumSphere();
} }
} }
// Aggregate initialization: // Aggregate initialization:
BerylliumSphere[] d = { new BerylliumSphere(), BerylliumSphere[] d = {new BerylliumSphere(),
new BerylliumSphere(), new BerylliumSphere() new BerylliumSphere(), new BerylliumSphere()
}; };
// Dynamic aggregate initialization: // Dynamic aggregate initialization:
@@ -41,10 +43,10 @@ public class ArrayOptions {
// automatically initialized to zero: // automatically initialized to zero:
print("f: " + Arrays.toString(f)); print("f: " + Arrays.toString(f));
int[] g = new int[4]; int[] g = new int[4];
for(int i = 0; i < g.length; i++) { for (int i = 0; i < g.length; i++) {
g[i] = i*i; g[i] = i * i;
} }
int[] h = { 11, 47, 93 }; int[] h = {11, 47, 93};
// Compile error: variable e not initialized: // Compile error: variable e not initialized:
//!print("e.length = " + e.length); //!print("e.length = " + e.length);
print("f.length = " + f.length); print("f.length = " + f.length);
@@ -52,7 +54,7 @@ public class ArrayOptions {
print("h.length = " + h.length); print("h.length = " + h.length);
e = h; e = h;
print("e.length = " + e.length); print("e.length = " + e.length);
e = new int[]{ 1, 2 }; e = new int[]{1, 2};
print("e.length = " + e.length); print("e.length = " + e.length);
} }
} /* Output: } /* Output:

View File

@@ -1,7 +1,10 @@
package arrays;//: arrays/ArraySearching.java package arrays;//: arrays/ArraySearching.java
// Using Arrays.binarySearch(). // Using Arrays.binarySearch().
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class ArraySearching { public class ArraySearching {
@@ -12,10 +15,10 @@ public class ArraySearching {
Generated.array(new Integer[25], gen)); Generated.array(new Integer[25], gen));
Arrays.sort(a); Arrays.sort(a);
print("Sorted array: " + Arrays.toString(a)); print("Sorted array: " + Arrays.toString(a));
while(true) { while (true) {
int r = gen.next(); int r = gen.next();
int location = Arrays.binarySearch(a, r); int location = Arrays.binarySearch(a, r);
if(location >= 0) { if (location >= 0) {
print("Location of " + r + " is " + location + print("Location of " + r + " is " + location +
", a[" + location + "] = " + a[location]); ", a[" + location + "] = " + a[location]);
break; // Out of while loop break; // Out of while loop

View File

@@ -1,14 +1,15 @@
package arrays;//: arrays/AssemblingMultidimensionalArrays.java package arrays;//: arrays/AssemblingMultidimensionalArrays.java
// Creating multidimensional arrays. // Creating multidimensional arrays.
import java.util.*; import java.util.*;
public class AssemblingMultidimensionalArrays { public class AssemblingMultidimensionalArrays {
public static void main(String[] args) { public static void main(String[] args) {
Integer[][] a; Integer[][] a;
a = new Integer[3][]; a = new Integer[3][];
for(int i = 0; i < a.length; i++) { for (int i = 0; i < a.length; i++) {
a[i] = new Integer[3]; a[i] = new Integer[3];
for(int j = 0; j < a[i].length; j++) { for (int j = 0; j < a[i].length; j++) {
a[i][j] = i * j; // Autoboxing a[i][j] = i * j; // Autoboxing
} }
} }

View File

@@ -1,13 +1,14 @@
package arrays;//: arrays/AutoboxingArrays.java package arrays;//: arrays/AutoboxingArrays.java
import java.util.*; import java.util.*;
public class AutoboxingArrays { public class AutoboxingArrays {
public static void main(String[] args) { public static void main(String[] args) {
Integer[][] a = { // Autoboxing: Integer[][] a = { // Autoboxing:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }, {21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
{ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 }, {51, 52, 53, 54, 55, 56, 57, 58, 59, 60},
{ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 }, {71, 72, 73, 74, 75, 76, 77, 78, 79, 80},
}; };
System.out.println(Arrays.deepToString(a)); System.out.println(Arrays.deepToString(a));
} }

View File

@@ -1,35 +1,47 @@
package arrays;//: arrays/CompType.java package arrays;//: arrays/CompType.java
// Implementing Comparable in a class. // Implementing Comparable in a class.
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class CompType implements Comparable<CompType> { public class CompType implements Comparable<CompType> {
int i; int i;
int j; int j;
private static int count = 1; private static int count = 1;
public CompType(int n1, int n2) { public CompType(int n1, int n2) {
i = n1; i = n1;
j = n2; j = n2;
} }
@Override
public String toString() { public String toString() {
String result = "[i = " + i + ", j = " + j + "]"; String result = "[i = " + i + ", j = " + j + "]";
if(count++ % 3 == 0) { if (count++ % 3 == 0) {
result += "\n"; result += "\n";
} }
return result; return result;
} }
@Override
public int compareTo(CompType rv) { public int compareTo(CompType rv) {
return (i < rv.i ? -1 : (i == rv.i ? 0 : 1)); return (i < rv.i ? -1 : (i == rv.i ? 0 : 1));
} }
private static Random r = new Random(47); private static Random r = new Random(47);
public static Generator<CompType> generator() { public static Generator<CompType> generator() {
return new Generator<CompType>() { return new Generator<CompType>() {
@Override
public CompType next() { public CompType next() {
return new CompType(r.nextInt(100),r.nextInt(100)); return new CompType(r.nextInt(100), r.nextInt(100));
} }
}; };
} }
public static void main(String[] args) { public static void main(String[] args) {
CompType[] a = CompType[] a =
Generated.array(new CompType[12], generator()); Generated.array(new CompType[12], generator());

View File

@@ -1,10 +1,14 @@
package arrays;//: arrays/ComparatorTest.java package arrays;//: arrays/ComparatorTest.java
// Implementing a Comparator for a class. // Implementing a Comparator for a class.
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
class CompTypeComparator implements Comparator<CompType> { class CompTypeComparator implements Comparator<CompType> {
@Override
public int compare(CompType o1, CompType o2) { public int compare(CompType o1, CompType o2) {
return (o1.j < o2.j ? -1 : (o1.j == o2.j ? 0 : 1)); return (o1.j < o2.j ? -1 : (o1.j == o2.j ? 0 : 1));
} }

View File

@@ -1,6 +1,8 @@
package arrays;//: arrays/ComparingArrays.java package arrays;//: arrays/ComparingArrays.java
// Using Arrays.equals() // Using Arrays.equals()
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class ComparingArrays { public class ComparingArrays {
@@ -14,8 +16,8 @@ public class ComparingArrays {
print(Arrays.equals(a1, a2)); print(Arrays.equals(a1, a2));
String[] s1 = new String[4]; String[] s1 = new String[4];
Arrays.fill(s1, "Hi"); Arrays.fill(s1, "Hi");
String[] s2 = { new String("Hi"), new String("Hi"), String[] s2 = {new String("Hi"), new String("Hi"),
new String("Hi"), new String("Hi") }; new String("Hi"), new String("Hi")};
print(Arrays.equals(s1, s2)); print(Arrays.equals(s1, s2));
} }
} /* Output: } /* Output:

View File

@@ -1,17 +1,23 @@
package arrays;//: arrays/ContainerComparison.java package arrays;//: arrays/ContainerComparison.java
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
class BerylliumSphere { class BerylliumSphere {
private static long counter; private static long counter;
private final long id = counter++; private final long id = counter++;
public String toString() { return "Sphere " + id; }
@Override
public String toString() {
return "Sphere " + id;
}
} }
public class ContainerComparison { public class ContainerComparison {
public static void main(String[] args) { public static void main(String[] args) {
BerylliumSphere[] spheres = new BerylliumSphere[10]; BerylliumSphere[] spheres = new BerylliumSphere[10];
for(int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
spheres[i] = new BerylliumSphere(); spheres[i] = new BerylliumSphere();
} }
print(Arrays.toString(spheres)); print(Arrays.toString(spheres));
@@ -19,13 +25,13 @@ public class ContainerComparison {
List<BerylliumSphere> sphereList = List<BerylliumSphere> sphereList =
new ArrayList<BerylliumSphere>(); new ArrayList<BerylliumSphere>();
for(int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
sphereList.add(new BerylliumSphere()); sphereList.add(new BerylliumSphere());
} }
print(sphereList); print(sphereList);
print(sphereList.get(4)); print(sphereList.get(4));
int[] integers = { 0, 1, 2, 3, 4, 5 }; int[] integers = {0, 1, 2, 3, 4, 5};
print(Arrays.toString(integers)); print(Arrays.toString(integers));
print(integers[4]); print(integers[4]);

View File

@@ -1,6 +1,8 @@
package arrays;//: arrays/CopyingArrays.java package arrays;//: arrays/CopyingArrays.java
// Using System.arraycopy() // Using System.arraycopy()
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class CopyingArrays { public class CopyingArrays {
@@ -27,7 +29,7 @@ public class CopyingArrays {
Arrays.fill(v, new Integer(99)); Arrays.fill(v, new Integer(99));
print("u = " + Arrays.toString(u)); print("u = " + Arrays.toString(u));
print("v = " + Arrays.toString(v)); print("v = " + Arrays.toString(v));
System.arraycopy(v, 0, u, u.length/2, v.length); System.arraycopy(v, 0, u, u.length / 2, v.length);
print("u = " + Arrays.toString(u)); print("u = " + Arrays.toString(u));
} }
} /* Output: } /* Output:

View File

@@ -1,6 +1,8 @@
package arrays;//: arrays/FillingArrays.java package arrays;//: arrays/FillingArrays.java
// Using Arrays.fill() // Using Arrays.fill()
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class FillingArrays { public class FillingArrays {
@@ -17,11 +19,11 @@ public class FillingArrays {
String[] a9 = new String[size]; String[] a9 = new String[size];
Arrays.fill(a1, true); Arrays.fill(a1, true);
print("a1 = " + Arrays.toString(a1)); print("a1 = " + Arrays.toString(a1));
Arrays.fill(a2, (byte)11); Arrays.fill(a2, (byte) 11);
print("a2 = " + Arrays.toString(a2)); print("a2 = " + Arrays.toString(a2));
Arrays.fill(a3, 'x'); Arrays.fill(a3, 'x');
print("a3 = " + Arrays.toString(a3)); print("a3 = " + Arrays.toString(a3));
Arrays.fill(a4, (short)17); Arrays.fill(a4, (short) 17);
print("a4 = " + Arrays.toString(a4)); print("a4 = " + Arrays.toString(a4));
Arrays.fill(a5, 19); Arrays.fill(a5, 19);
print("a5 = " + Arrays.toString(a5)); print("a5 = " + Arrays.toString(a5));

View File

@@ -1,22 +1,25 @@
package arrays;//: arrays/GeneratorsTest.java package arrays;//: arrays/GeneratorsTest.java
import net.mindview.util.*; import net.mindview.util.*;
public class GeneratorsTest { public class GeneratorsTest {
public static int size = 10; public static int size = 10;
public static void test(Class<?> surroundingClass) { public static void test(Class<?> surroundingClass) {
for(Class<?> type : surroundingClass.getClasses()) { for (Class<?> type : surroundingClass.getClasses()) {
System.out.print(type.getSimpleName() + ": "); System.out.print(type.getSimpleName() + ": ");
try { try {
Generator<?> g = (Generator<?>)type.newInstance(); Generator<?> g = (Generator<?>) type.newInstance();
for(int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
System.out.printf(g.next() + " "); System.out.printf(g.next() + " ");
} }
System.out.println(); System.out.println();
} catch(Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
test(CountingGenerator.class); test(CountingGenerator.class);
} }

View File

@@ -1,5 +1,6 @@
package arrays;//: arrays/IceCream.java package arrays;//: arrays/IceCream.java
// Returning arrays from methods. // Returning arrays from methods.
import java.util.*; import java.util.*;
public class IceCream { public class IceCream {
@@ -9,25 +10,27 @@ public class IceCream {
"Mint Chip", "Mocha Almond Fudge", "Rum Raisin", "Mint Chip", "Mocha Almond Fudge", "Rum Raisin",
"Praline Cream", "Mud Pie" "Praline Cream", "Mud Pie"
}; };
public static String[] flavorSet(int n) { public static String[] flavorSet(int n) {
if(n > FLAVORS.length) { if (n > FLAVORS.length) {
throw new IllegalArgumentException("Set too big"); throw new IllegalArgumentException("Set too big");
} }
String[] results = new String[n]; String[] results = new String[n];
boolean[] picked = new boolean[FLAVORS.length]; boolean[] picked = new boolean[FLAVORS.length];
for(int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int t; int t;
do { do {
t = rand.nextInt(FLAVORS.length); t = rand.nextInt(FLAVORS.length);
} }
while(picked[t]); while (picked[t]);
results[i] = FLAVORS[t]; results[i] = FLAVORS[t];
picked[t] = true; picked[t] = true;
} }
return results; return results;
} }
public static void main(String[] args) { public static void main(String[] args) {
for(int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
System.out.println(Arrays.toString(flavorSet(3))); System.out.println(Arrays.toString(flavorSet(3)));
} }
} }

View File

@@ -1,22 +1,23 @@
package arrays;//: arrays/MultiDimWrapperArray.java package arrays;//: arrays/MultiDimWrapperArray.java
// Multidimensional arrays of "wrapper" objects. // Multidimensional arrays of "wrapper" objects.
import java.util.*; import java.util.*;
public class MultiDimWrapperArray { public class MultiDimWrapperArray {
public static void main(String[] args) { public static void main(String[] args) {
Integer[][] a1 = { // Autoboxing Integer[][] a1 = { // Autoboxing
{ 1, 2, 3, }, {1, 2, 3,},
{ 4, 5, 6, }, {4, 5, 6,},
}; };
Double[][][] a2 = { // Autoboxing Double[][][] a2 = { // Autoboxing
{ { 1.1, 2.2 }, { 3.3, 4.4 } }, {{1.1, 2.2}, {3.3, 4.4}},
{ { 5.5, 6.6 }, { 7.7, 8.8 } }, {{5.5, 6.6}, {7.7, 8.8}},
{ { 9.9, 1.2 }, { 2.3, 3.4 } }, {{9.9, 1.2}, {2.3, 3.4}},
}; };
String[][] a3 = { String[][] a3 = {
{ "The", "Quick", "Sly", "Fox" }, {"The", "Quick", "Sly", "Fox"},
{ "Jumped", "Over" }, {"Jumped", "Over"},
{ "The", "Lazy", "Brown", "Dog", "and", "friend" }, {"The", "Lazy", "Brown", "Dog", "and", "friend"},
}; };
System.out.println("a1: " + Arrays.deepToString(a1)); System.out.println("a1: " + Arrays.deepToString(a1));
System.out.println("a2: " + Arrays.deepToString(a2)); System.out.println("a2: " + Arrays.deepToString(a2));

View File

@@ -1,16 +1,17 @@
package arrays;//: arrays/MultidimensionalObjectArrays.java package arrays;//: arrays/MultidimensionalObjectArrays.java
import java.util.*; import java.util.*;
public class MultidimensionalObjectArrays { public class MultidimensionalObjectArrays {
public static void main(String[] args) { public static void main(String[] args) {
BerylliumSphere[][] spheres = { BerylliumSphere[][] spheres = {
{ new BerylliumSphere(), new BerylliumSphere() }, {new BerylliumSphere(), new BerylliumSphere()},
{ new BerylliumSphere(), new BerylliumSphere(), {new BerylliumSphere(), new BerylliumSphere(),
new BerylliumSphere(), new BerylliumSphere() }, new BerylliumSphere(), new BerylliumSphere()},
{ new BerylliumSphere(), new BerylliumSphere(), {new BerylliumSphere(), new BerylliumSphere(),
new BerylliumSphere(), new BerylliumSphere(), new BerylliumSphere(), new BerylliumSphere(),
new BerylliumSphere(), new BerylliumSphere(), new BerylliumSphere(), new BerylliumSphere(),
new BerylliumSphere(), new BerylliumSphere() }, new BerylliumSphere(), new BerylliumSphere()},
}; };
System.out.println(Arrays.deepToString(spheres)); System.out.println(Arrays.deepToString(spheres));
} }

View File

@@ -1,12 +1,13 @@
package arrays;//: arrays/MultidimensionalPrimitiveArray.java package arrays;//: arrays/MultidimensionalPrimitiveArray.java
// Creating multidimensional arrays. // Creating multidimensional arrays.
import java.util.*; import java.util.*;
public class MultidimensionalPrimitiveArray { public class MultidimensionalPrimitiveArray {
public static void main(String[] args) { public static void main(String[] args) {
int[][] a = { int[][] a = {
{ 1, 2, 3, }, {1, 2, 3,},
{ 4, 5, 6, }, {4, 5, 6,},
}; };
System.out.println(Arrays.deepToString(a)); System.out.println(Arrays.deepToString(a));
} }

View File

@@ -1,17 +1,21 @@
package arrays;//: arrays/ParameterizedArrayType.java package arrays;//: arrays/ParameterizedArrayType.java
class ClassParameter<T> { class ClassParameter<T> {
public T[] f(T[] arg) { return arg; } public T[] f(T[] arg) {
return arg;
}
} }
class MethodParameter { class MethodParameter {
public static <T> T[] f(T[] arg) { return arg; } public static <T> T[] f(T[] arg) {
return arg;
}
} }
public class ParameterizedArrayType { public class ParameterizedArrayType {
public static void main(String[] args) { public static void main(String[] args) {
Integer[] ints = { 1, 2, 3, 4, 5 }; Integer[] ints = {1, 2, 3, 4, 5};
Double[] doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 }; Double[] doubles = {1.1, 2.2, 3.3, 4.4, 5.5};
Integer[] ints2 = Integer[] ints2 =
new ClassParameter<Integer>().f(ints); new ClassParameter<Integer>().f(ints);
Double[] doubles2 = Double[] doubles2 =

View File

@@ -1,5 +1,7 @@
package arrays;//: arrays/PrimitiveConversionDemonstration.java package arrays;//: arrays/PrimitiveConversionDemonstration.java
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
public class PrimitiveConversionDemonstration { public class PrimitiveConversionDemonstration {

View File

@@ -1,4 +1,5 @@
package arrays;//: arrays/RaggedArray.java package arrays;//: arrays/RaggedArray.java
import java.util.*; import java.util.*;
public class RaggedArray { public class RaggedArray {
@@ -6,9 +7,9 @@ public class RaggedArray {
Random rand = new Random(47); Random rand = new Random(47);
// 3-D array with varied-length vectors: // 3-D array with varied-length vectors:
int[][][] a = new int[rand.nextInt(7)][][]; int[][][] a = new int[rand.nextInt(7)][][];
for(int i = 0; i < a.length; i++) { for (int i = 0; i < a.length; i++) {
a[i] = new int[rand.nextInt(5)][]; a[i] = new int[rand.nextInt(5)][];
for(int j = 0; j < a[i].length; j++) { for (int j = 0; j < a[i].length; j++) {
a[i][j] = new int[rand.nextInt(5)]; a[i][j] = new int[rand.nextInt(5)];
} }
} }

View File

@@ -1,4 +1,5 @@
package arrays;//: arrays/RandomGeneratorsTest.java package arrays;//: arrays/RandomGeneratorsTest.java
import net.mindview.util.*; import net.mindview.util.*;
public class RandomGeneratorsTest { public class RandomGeneratorsTest {

View File

@@ -1,7 +1,10 @@
package arrays;//: arrays/Reverse.java package arrays;//: arrays/Reverse.java
// The Collections.reverseOrder() Comparator // The Collections.reverseOrder() Comparator
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class Reverse { public class Reverse {

View File

@@ -1,7 +1,10 @@
package arrays;//: arrays/StringSorting.java package arrays;//: arrays/StringSorting.java
// Sorting an array of Strings. // Sorting an array of Strings.
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class StringSorting { public class StringSorting {

View File

@@ -1,7 +1,10 @@
package arrays;//: arrays/TestArrayGeneration.java package arrays;//: arrays/TestArrayGeneration.java
// Test the tools that use generators to fill arrays. // Test the tools that use generators to fill arrays.
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class TestArrayGeneration { public class TestArrayGeneration {

View File

@@ -1,12 +1,14 @@
package arrays;//: arrays/TestGenerated.java package arrays;//: arrays/TestGenerated.java
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
public class TestGenerated { public class TestGenerated {
public static void main(String[] args) { public static void main(String[] args) {
Integer[] a = { 9, 8, 7, 6 }; Integer[] a = {9, 8, 7, 6};
System.out.println(Arrays.toString(a)); System.out.println(Arrays.toString(a));
a = Generated.array(a,new CountingGenerator.Integer()); a = Generated.array(a, new CountingGenerator.Integer());
System.out.println(Arrays.toString(a)); System.out.println(Arrays.toString(a));
Integer[] b = Generated.array(Integer.class, Integer[] b = Generated.array(Integer.class,
new CountingGenerator.Integer(), 15); new CountingGenerator.Integer(), 15);

View File

@@ -1,4 +1,5 @@
package arrays;//: arrays/ThreeDWithNew.java package arrays;//: arrays/ThreeDWithNew.java
import java.util.*; import java.util.*;
public class ThreeDWithNew { public class ThreeDWithNew {

View File

@@ -1,6 +1,7 @@
//: bangbean/BangBean.java //: bangbean/BangBean.java
// A graphical Bean. // A graphical Bean.
package bangbean; package bangbean;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
@@ -15,68 +16,95 @@ BangBean extends JPanel implements Serializable {
private int fontSize = 48; private int fontSize = 48;
private Color tColor = Color.RED; private Color tColor = Color.RED;
private ActionListener actionListener; private ActionListener actionListener;
public BangBean() { public BangBean() {
addMouseListener(new ML()); addMouseListener(new ML());
addMouseMotionListener(new MML()); addMouseMotionListener(new MML());
} }
public int getCircleSize() { return cSize; }
public int getCircleSize() {
return cSize;
}
public void setCircleSize(int newSize) { public void setCircleSize(int newSize) {
cSize = newSize; cSize = newSize;
} }
public String getBangText() { return text; }
public String getBangText() {
return text;
}
public void setBangText(String newText) { public void setBangText(String newText) {
text = newText; text = newText;
} }
public int getFontSize() { return fontSize; }
public int getFontSize() {
return fontSize;
}
public void setFontSize(int newSize) { public void setFontSize(int newSize) {
fontSize = newSize; fontSize = newSize;
} }
public Color getTextColor() { return tColor; }
public Color getTextColor() {
return tColor;
}
public void setTextColor(Color newColor) { public void setTextColor(Color newColor) {
tColor = newColor; tColor = newColor;
} }
@Override
public void paintComponent(Graphics g) { public void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.drawOval(xm - cSize/2, ym - cSize/2, cSize, cSize); g.drawOval(xm - cSize / 2, ym - cSize / 2, cSize, cSize);
} }
// This is a unicast listener, which is // This is a unicast listener, which is
// the simplest form of listener management: // the simplest form of listener management:
public void addActionListener(ActionListener l) public void addActionListener(ActionListener l)
throws TooManyListenersException { throws TooManyListenersException {
if(actionListener != null) { if (actionListener != null) {
throw new TooManyListenersException(); throw new TooManyListenersException();
} }
actionListener = l; actionListener = l;
} }
public void removeActionListener(ActionListener l) { public void removeActionListener(ActionListener l) {
actionListener = null; actionListener = null;
} }
class ML extends MouseAdapter { class ML extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
Graphics g = getGraphics(); Graphics g = getGraphics();
g.setColor(tColor); g.setColor(tColor);
g.setFont( g.setFont(
new Font("TimesRoman", Font.BOLD, fontSize)); new Font("TimesRoman", Font.BOLD, fontSize));
int width = g.getFontMetrics().stringWidth(text); int width = g.getFontMetrics().stringWidth(text);
g.drawString(text, (getSize().width - width) /2, g.drawString(text, (getSize().width - width) / 2,
getSize().height/2); getSize().height / 2);
g.dispose(); g.dispose();
// Call the listener's method: // Call the listener's method:
if(actionListener != null) { if (actionListener != null) {
actionListener.actionPerformed( actionListener.actionPerformed(
new ActionEvent(BangBean.this, new ActionEvent(BangBean.this,
ActionEvent.ACTION_PERFORMED, null)); ActionEvent.ACTION_PERFORMED, null));
} }
} }
} }
class MML extends MouseMotionAdapter { class MML extends MouseMotionAdapter {
@Override
public void mouseMoved(MouseEvent e) { public void mouseMoved(MouseEvent e) {
xm = e.getX(); xm = e.getX();
ym = e.getY(); ym = e.getY();
repaint(); repaint();
} }
} }
@Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
return new Dimension(200, 200); return new Dimension(200, 200);
} }

View File

@@ -1,31 +1,38 @@
//: bangbean/BangBeanTest.java //: bangbean/BangBeanTest.java
// {Timeout: 5} Abort after 5 seconds when testing // {Timeout: 5} Abort after 5 seconds when testing
package bangbean; package bangbean;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.util.*; import java.util.*;
import static net.mindview.util.SwingConsole.*; import static net.mindview.util.SwingConsole.*;
public class BangBeanTest extends JFrame { public class BangBeanTest extends JFrame {
private JTextField txt = new JTextField(20); private JTextField txt = new JTextField(20);
// During testing, report actions: // During testing, report actions:
class BBL implements ActionListener { class BBL implements ActionListener {
private int count = 0; private int count = 0;
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
txt.setText("BangBean action "+ count++); txt.setText("BangBean action " + count++);
} }
} }
public BangBeanTest() { public BangBeanTest() {
BangBean bb = new BangBean(); BangBean bb = new BangBean();
try { try {
bb.addActionListener(new BBL()); bb.addActionListener(new BBL());
} catch(TooManyListenersException e) { } catch (TooManyListenersException e) {
txt.setText("Too many listeners"); txt.setText("Too many listeners");
} }
add(bb); add(bb);
add(BorderLayout.SOUTH, txt); add(BorderLayout.SOUTH, txt);
} }
public static void main(String[] args) { public static void main(String[] args) {
run(new BangBeanTest(), 400, 500); run(new BangBeanTest(), 400, 500);
} }

View File

@@ -2,27 +2,32 @@ package concurrency;//: concurrency/ActiveObjectDemo.java
// Can only pass constants, immutables, "disconnected // Can only pass constants, immutables, "disconnected
// objects," or other active objects as arguments // objects," or other active objects as arguments
// to asynch methods. // to asynch methods.
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class ActiveObjectDemo { public class ActiveObjectDemo {
private ExecutorService ex = private ExecutorService ex =
Executors.newSingleThreadExecutor(); Executors.newSingleThreadExecutor();
private Random rand = new Random(47); private Random rand = new Random(47);
// Insert a random delay to produce the effect // Insert a random delay to produce the effect
// of a calculation time: // of a calculation time:
private void pause(int factor) { private void pause(int factor) {
try { try {
TimeUnit.MILLISECONDS.sleep( TimeUnit.MILLISECONDS.sleep(
100 + rand.nextInt(factor)); 100 + rand.nextInt(factor));
} catch(InterruptedException e) { } catch (InterruptedException e) {
print("sleep() interrupted"); print("sleep() interrupted");
} }
} }
public Future<Integer> public Future<Integer>
calculateInt(final int x, final int y) { calculateInt(final int x, final int y) {
return ex.submit(new Callable<Integer>() { return ex.submit(new Callable<Integer>() {
@Override
public Integer call() { public Integer call() {
print("starting " + x + " + " + y); print("starting " + x + " + " + y);
pause(500); pause(500);
@@ -30,9 +35,11 @@ public class ActiveObjectDemo {
} }
}); });
} }
public Future<Float> public Future<Float>
calculateFloat(final float x, final float y) { calculateFloat(final float x, final float y) {
return ex.submit(new Callable<Float>() { return ex.submit(new Callable<Float>() {
@Override
public Float call() { public Float call() {
print("starting " + x + " + " + y); print("starting " + x + " + " + y);
pause(2000); pause(2000);
@@ -40,25 +47,29 @@ public class ActiveObjectDemo {
} }
}); });
} }
public void shutdown() { ex.shutdown(); }
public void shutdown() {
ex.shutdown();
}
public static void main(String[] args) { public static void main(String[] args) {
ActiveObjectDemo d1 = new ActiveObjectDemo(); ActiveObjectDemo d1 = new ActiveObjectDemo();
// Prevents ConcurrentModificationException: // Prevents ConcurrentModificationException:
List<Future<?>> results = List<Future<?>> results =
new CopyOnWriteArrayList<Future<?>>(); new CopyOnWriteArrayList<Future<?>>();
for(float f = 0.0f; f < 1.0f; f += 0.2f) { for (float f = 0.0f; f < 1.0f; f += 0.2f) {
results.add(d1.calculateFloat(f, f)); results.add(d1.calculateFloat(f, f));
} }
for(int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
results.add(d1.calculateInt(i, i)); results.add(d1.calculateInt(i, i));
} }
print("All asynch calls made"); print("All asynch calls made");
while(results.size() > 0) { while (results.size() > 0) {
for(Future<?> f : results) { for (Future<?> f : results) {
if(f.isDone()) { if (f.isDone()) {
try { try {
print(f.get()); print(f.get());
} catch(Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
results.remove(f); results.remove(f);

View File

@@ -1,14 +1,18 @@
package concurrency;//: concurrency/AtomicEvenGenerator.java package concurrency;//: concurrency/AtomicEvenGenerator.java
// Atomic classes are occasionally useful in regular code. // Atomic classes are occasionally useful in regular code.
// {RunByHand} // {RunByHand}
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
public class AtomicEvenGenerator extends IntGenerator { public class AtomicEvenGenerator extends IntGenerator {
private AtomicInteger currentEvenValue = private AtomicInteger currentEvenValue =
new AtomicInteger(0); new AtomicInteger(0);
@Override
public int next() { public int next() {
return currentEvenValue.addAndGet(2); return currentEvenValue.addAndGet(2);
} }
public static void main(String[] args) { public static void main(String[] args) {
EvenChecker.test(new AtomicEvenGenerator()); EvenChecker.test(new AtomicEvenGenerator());
} }

View File

@@ -1,19 +1,30 @@
package concurrency;//: concurrency/AtomicIntegerTest.java package concurrency;//: concurrency/AtomicIntegerTest.java
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
import java.util.*; import java.util.*;
public class AtomicIntegerTest implements Runnable { public class AtomicIntegerTest implements Runnable {
private AtomicInteger i = new AtomicInteger(0); private AtomicInteger i = new AtomicInteger(0);
public int getValue() { return i.get(); }
private void evenIncrement() { i.addAndGet(2); } public int getValue() {
return i.get();
}
private void evenIncrement() {
i.addAndGet(2);
}
@Override
public void run() { public void run() {
while(true) { while (true) {
evenIncrement(); evenIncrement();
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
new Timer().schedule(new TimerTask() { new Timer().schedule(new TimerTask() {
@Override
public void run() { public void run() {
System.err.println("Aborting"); System.err.println("Aborting");
System.exit(0); System.exit(0);
@@ -22,9 +33,9 @@ public class AtomicIntegerTest implements Runnable {
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
AtomicIntegerTest ait = new AtomicIntegerTest(); AtomicIntegerTest ait = new AtomicIntegerTest();
exec.execute(ait); exec.execute(ait);
while(true) { while (true) {
int val = ait.getValue(); int val = ait.getValue();
if(val % 2 != 0) { if (val % 2 != 0) {
System.out.println(val); System.out.println(val);
System.exit(0); System.exit(0);
} }

View File

@@ -3,8 +3,14 @@ package concurrency;//: concurrency/Atomicity.java
public class Atomicity { public class Atomicity {
int i; int i;
void f1() { i++; }
void f2() { i += 3; } void f1() {
i++;
}
void f2() {
i += 3;
}
} /* Output: (Sample) } /* Output: (Sample)
... ...
void f1(); void f1();

View File

@@ -1,22 +1,33 @@
package concurrency;//: concurrency/AtomicityTest.java package concurrency;//: concurrency/AtomicityTest.java
import java.util.concurrent.*; import java.util.concurrent.*;
public class AtomicityTest implements Runnable { public class AtomicityTest implements Runnable {
private int i = 0; private int i = 0;
public int getValue() { return i; }
private synchronized void evenIncrement() { i++; i++; } public int getValue() {
return i;
}
private synchronized void evenIncrement() {
i++;
i++;
}
@Override
public void run() { public void run() {
while(true) { while (true) {
evenIncrement(); evenIncrement();
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest(); AtomicityTest at = new AtomicityTest();
exec.execute(at); exec.execute(at);
while(true) { while (true) {
int val = at.getValue(); int val = at.getValue();
if(val % 2 != 0) { if (val % 2 != 0) {
System.out.println(val); System.out.println(val);
System.exit(0); System.exit(0);
} }

View File

@@ -1,44 +1,52 @@
package concurrency;//: concurrency/AttemptLocking.java package concurrency;//: concurrency/AttemptLocking.java
// Locks in the concurrent library allow you // Locks in the concurrent library allow you
// to give up on trying to acquire a lock. // to give up on trying to acquire a lock.
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.locks.*; import java.util.concurrent.locks.*;
public class AttemptLocking { public class AttemptLocking {
private ReentrantLock lock = new ReentrantLock(); private ReentrantLock lock = new ReentrantLock();
public void untimed() { public void untimed() {
boolean captured = lock.tryLock(); boolean captured = lock.tryLock();
try { try {
System.out.println("tryLock(): " + captured); System.out.println("tryLock(): " + captured);
} finally { } finally {
if(captured) { if (captured) {
lock.unlock(); lock.unlock();
} }
} }
} }
public void timed() { public void timed() {
boolean captured = false; boolean captured = false;
try { try {
captured = lock.tryLock(2, TimeUnit.SECONDS); captured = lock.tryLock(2, TimeUnit.SECONDS);
} catch(InterruptedException e) { } catch (InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
try { try {
System.out.println("tryLock(2, TimeUnit.SECONDS): " + System.out.println("tryLock(2, TimeUnit.SECONDS): " +
captured); captured);
} finally { } finally {
if(captured) { if (captured) {
lock.unlock(); lock.unlock();
} }
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
final AttemptLocking al = new AttemptLocking(); final AttemptLocking al = new AttemptLocking();
al.untimed(); // True -- lock is available al.untimed(); // True -- lock is available
al.timed(); // True -- lock is available al.timed(); // True -- lock is available
// Now create a separate task to grab the lock: // Now create a separate task to grab the lock:
new Thread() { new Thread() {
{ setDaemon(true); } {
setDaemon(true);
}
@Override
public void run() { public void run() {
al.lock.lock(); al.lock.lock();
System.out.println("acquired"); System.out.println("acquired");

View File

@@ -1,14 +1,23 @@
package concurrency;//: concurrency/BankTellerSimulation.java package concurrency;//: concurrency/BankTellerSimulation.java
// Using queues and multithreading. // Using queues and multithreading.
// {Args: 5} // {Args: 5}
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.*; import java.util.*;
// Read-only objects don't require synchronization: // Read-only objects don't require synchronization:
class Customer { class Customer {
private final int serviceTime; private final int serviceTime;
public Customer(int tm) { serviceTime = tm; }
public int getServiceTime() { return serviceTime; } public Customer(int tm) {
serviceTime = tm;
}
public int getServiceTime() {
return serviceTime;
}
@Override
public String toString() { public String toString() {
return "[" + serviceTime + "]"; return "[" + serviceTime + "]";
} }
@@ -19,12 +28,14 @@ class CustomerLine extends ArrayBlockingQueue<Customer> {
public CustomerLine(int maxLineSize) { public CustomerLine(int maxLineSize) {
super(maxLineSize); super(maxLineSize);
} }
@Override
public String toString() { public String toString() {
if(this.size() == 0) { if (this.size() == 0) {
return "[Empty]"; return "[Empty]";
} }
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
for(Customer customer : this) { for (Customer customer : this) {
result.append(customer); result.append(customer);
} }
return result.toString(); return result.toString();
@@ -35,16 +46,19 @@ class CustomerLine extends ArrayBlockingQueue<Customer> {
class CustomerGenerator implements Runnable { class CustomerGenerator implements Runnable {
private CustomerLine customers; private CustomerLine customers;
private static Random rand = new Random(47); private static Random rand = new Random(47);
public CustomerGenerator(CustomerLine cq) { public CustomerGenerator(CustomerLine cq) {
customers = cq; customers = cq;
} }
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(rand.nextInt(300)); TimeUnit.MILLISECONDS.sleep(rand.nextInt(300));
customers.put(new Customer(rand.nextInt(1000))); customers.put(new Customer(rand.nextInt(1000)));
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
System.out.println("CustomerGenerator interrupted"); System.out.println("CustomerGenerator interrupted");
} }
System.out.println("CustomerGenerator terminating"); System.out.println("CustomerGenerator terminating");
@@ -58,37 +72,53 @@ class Teller implements Runnable, Comparable<Teller> {
private int customersServed = 0; private int customersServed = 0;
private CustomerLine customers; private CustomerLine customers;
private boolean servingCustomerLine = true; private boolean servingCustomerLine = true;
public Teller(CustomerLine cq) { customers = cq; }
public Teller(CustomerLine cq) {
customers = cq;
}
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
Customer customer = customers.take(); Customer customer = customers.take();
TimeUnit.MILLISECONDS.sleep( TimeUnit.MILLISECONDS.sleep(
customer.getServiceTime()); customer.getServiceTime());
synchronized(this) { synchronized (this) {
customersServed++; customersServed++;
while(!servingCustomerLine) { while (!servingCustomerLine) {
wait(); wait();
} }
} }
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
System.out.println(this + "interrupted"); System.out.println(this + "interrupted");
} }
System.out.println(this + "terminating"); System.out.println(this + "terminating");
} }
public synchronized void doSomethingElse() { public synchronized void doSomethingElse() {
customersServed = 0; customersServed = 0;
servingCustomerLine = false; servingCustomerLine = false;
} }
public synchronized void serveCustomerLine() { public synchronized void serveCustomerLine() {
assert !servingCustomerLine:"already serving: " + this; assert !servingCustomerLine : "already serving: " + this;
servingCustomerLine = true; servingCustomerLine = true;
notifyAll(); notifyAll();
} }
public String toString() { return "Teller " + id + " "; }
public String shortString() { return "T" + id; } @Override
public String toString() {
return "Teller " + id + " ";
}
public String shortString() {
return "T" + id;
}
// Used by priority queue: // Used by priority queue:
@Override
public synchronized int compareTo(Teller other) { public synchronized int compareTo(Teller other) {
return customersServed < other.customersServed ? -1 : return customersServed < other.customersServed ? -1 :
(customersServed == other.customersServed ? 0 : 1); (customersServed == other.customersServed ? 0 : 1);
@@ -104,6 +134,7 @@ class TellerManager implements Runnable {
new LinkedList<Teller>(); new LinkedList<Teller>();
private int adjustmentPeriod; private int adjustmentPeriod;
private static Random rand = new Random(47); private static Random rand = new Random(47);
public TellerManager(ExecutorService e, public TellerManager(ExecutorService e,
CustomerLine customers, int adjustmentPeriod) { CustomerLine customers, int adjustmentPeriod) {
exec = e; exec = e;
@@ -114,15 +145,16 @@ class TellerManager implements Runnable {
exec.execute(teller); exec.execute(teller);
workingTellers.add(teller); workingTellers.add(teller);
} }
public void adjustTellerNumber() { public void adjustTellerNumber() {
// This is actually a control system. By adjusting // This is actually a control system. By adjusting
// the numbers, you can reveal stability issues in // the numbers, you can reveal stability issues in
// the control mechanism. // the control mechanism.
// If line is too long, add another teller: // If line is too long, add another teller:
if(customers.size() / workingTellers.size() > 2) { if (customers.size() / workingTellers.size() > 2) {
// If tellers are on break or doing // If tellers are on break or doing
// another job, bring one back: // another job, bring one back:
if(tellersDoingOtherThings.size() > 0) { if (tellersDoingOtherThings.size() > 0) {
Teller teller = tellersDoingOtherThings.remove(); Teller teller = tellersDoingOtherThings.remove();
teller.serveCustomerLine(); teller.serveCustomerLine();
workingTellers.offer(teller); workingTellers.offer(teller);
@@ -135,45 +167,53 @@ class TellerManager implements Runnable {
return; return;
} }
// If line is short enough, remove a teller: // If line is short enough, remove a teller:
if(workingTellers.size() > 1 && if (workingTellers.size() > 1 &&
customers.size() / workingTellers.size() < 2) { customers.size() / workingTellers.size() < 2) {
reassignOneTeller(); reassignOneTeller();
} }
// If there is no line, we only need one teller: // If there is no line, we only need one teller:
if(customers.size() == 0) { if (customers.size() == 0) {
while(workingTellers.size() > 1) { while (workingTellers.size() > 1) {
reassignOneTeller(); reassignOneTeller();
} }
} }
} }
// Give a teller a different job or a break: // Give a teller a different job or a break:
private void reassignOneTeller() { private void reassignOneTeller() {
Teller teller = workingTellers.poll(); Teller teller = workingTellers.poll();
teller.doSomethingElse(); teller.doSomethingElse();
tellersDoingOtherThings.offer(teller); tellersDoingOtherThings.offer(teller);
} }
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(adjustmentPeriod); TimeUnit.MILLISECONDS.sleep(adjustmentPeriod);
adjustTellerNumber(); adjustTellerNumber();
System.out.print(customers + " { "); System.out.print(customers + " { ");
for(Teller teller : workingTellers) { for (Teller teller : workingTellers) {
System.out.print(teller.shortString() + " "); System.out.print(teller.shortString() + " ");
} }
System.out.println("}"); System.out.println("}");
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
System.out.println(this + "interrupted"); System.out.println(this + "interrupted");
} }
System.out.println(this + "terminating"); System.out.println(this + "terminating");
} }
public String toString() { return "TellerManager "; }
@Override
public String toString() {
return "TellerManager ";
}
} }
public class BankTellerSimulation { public class BankTellerSimulation {
static final int MAX_LINE_SIZE = 50; static final int MAX_LINE_SIZE = 50;
static final int ADJUSTMENT_PERIOD = 1000; static final int ADJUSTMENT_PERIOD = 1000;
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
// If line is too long, customers will leave: // If line is too long, customers will leave:
@@ -183,7 +223,7 @@ public class BankTellerSimulation {
// Manager will add and remove tellers as necessary: // Manager will add and remove tellers as necessary:
exec.execute(new TellerManager( exec.execute(new TellerManager(
exec, customers, ADJUSTMENT_PERIOD)); exec, customers, ADJUSTMENT_PERIOD));
if(args.length > 0) // Optional argument if (args.length > 0) // Optional argument
{ {
TimeUnit.SECONDS.sleep(new Integer(args[0])); TimeUnit.SECONDS.sleep(new Integer(args[0]));
} else { } else {

View File

@@ -1,10 +1,11 @@
package concurrency;//: concurrency/CachedThreadPool.java package concurrency;//: concurrency/CachedThreadPool.java
import java.util.concurrent.*; import java.util.concurrent.*;
public class CachedThreadPool { public class CachedThreadPool {
public static void main(String[] args) { public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
exec.execute(new LiftOff()); exec.execute(new LiftOff());
} }
exec.shutdown(); exec.shutdown();

View File

@@ -1,12 +1,16 @@
package concurrency;//: concurrency/CallableDemo.java package concurrency;//: concurrency/CallableDemo.java
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.*; import java.util.*;
class TaskWithResult implements Callable<String> { class TaskWithResult implements Callable<String> {
private int id; private int id;
public TaskWithResult(int id) { public TaskWithResult(int id) {
this.id = id; this.id = id;
} }
@Override
public String call() { public String call() {
return "result of TaskWithResult " + id; return "result of TaskWithResult " + id;
} }
@@ -17,17 +21,17 @@ public class CallableDemo {
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = ArrayList<Future<String>> results =
new ArrayList<Future<String>>(); new ArrayList<Future<String>>();
for(int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
results.add(exec.submit(new TaskWithResult(i))); results.add(exec.submit(new TaskWithResult(i)));
} }
for(Future<String> fs : results) { for (Future<String> fs : results) {
try { try {
// get() blocks until completion: // get() blocks until completion:
System.out.println(fs.get()); System.out.println(fs.get());
} catch(InterruptedException e) { } catch (InterruptedException e) {
System.out.println(e); System.out.println(e);
return; return;
} catch(ExecutionException e) { } catch (ExecutionException e) {
System.out.println(e); System.out.println(e);
} finally { } finally {
exec.shutdown(); exec.shutdown();

View File

@@ -1,7 +1,9 @@
package concurrency;//: concurrency/CaptureUncaughtException.java package concurrency;//: concurrency/CaptureUncaughtException.java
import java.util.concurrent.*; import java.util.concurrent.*;
class ExceptionThread2 implements Runnable { class ExceptionThread2 implements Runnable {
@Override
public void run() { public void run() {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
System.out.println("run() by " + t); System.out.println("run() by " + t);
@@ -12,13 +14,15 @@ class ExceptionThread2 implements Runnable {
} }
class MyUncaughtExceptionHandler implements class MyUncaughtExceptionHandler implements
Thread.UncaughtExceptionHandler { Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) { public void uncaughtException(Thread t, Throwable e) {
System.out.println("caught " + e); System.out.println("caught " + e);
} }
} }
class HandlerThreadFactory implements ThreadFactory { class HandlerThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) { public Thread newThread(Runnable r) {
System.out.println(this + " creating new Thread"); System.out.println(this + " creating new Thread");
Thread t = new Thread(r); Thread t = new Thread(r);

View File

@@ -1,22 +1,42 @@
package concurrency;//: concurrency/CarBuilder.java package concurrency;//: concurrency/CarBuilder.java
// A complex example of tasks working together. // A complex example of tasks working together.
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
class Car { class Car {
private final int id; private final int id;
private boolean private boolean
engine = false, driveTrain = false, wheels = false; engine = false, driveTrain = false, wheels = false;
public Car(int idn) { id = idn; }
public Car(int idn) {
id = idn;
}
// Empty Car object: // Empty Car object:
public Car() { id = -1; } public Car() {
public synchronized int getId() { return id; } id = -1;
public synchronized void addEngine() { engine = true; } }
public synchronized int getId() {
return id;
}
public synchronized void addEngine() {
engine = true;
}
public synchronized void addDriveTrain() { public synchronized void addDriveTrain() {
driveTrain = true; driveTrain = true;
} }
public synchronized void addWheels() { wheels = true; }
public synchronized void addWheels() {
wheels = true;
}
@Override
public synchronized String toString() { public synchronized String toString() {
return "Car " + id + " [" + " engine: " + engine return "Car " + id + " [" + " engine: " + engine
+ " driveTrain: " + driveTrain + " driveTrain: " + driveTrain
@@ -24,15 +44,21 @@ class Car {
} }
} }
class CarQueue extends LinkedBlockingQueue<Car> {} class CarQueue extends LinkedBlockingQueue<Car> {
}
class ChassisBuilder implements Runnable { class ChassisBuilder implements Runnable {
private CarQueue carQueue; private CarQueue carQueue;
private int counter = 0; private int counter = 0;
public ChassisBuilder(CarQueue cq) { carQueue = cq; }
public ChassisBuilder(CarQueue cq) {
carQueue = cq;
}
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(500); TimeUnit.MILLISECONDS.sleep(500);
// Make chassis: // Make chassis:
Car c = new Car(counter++); Car c = new Car(counter++);
@@ -40,7 +66,7 @@ class ChassisBuilder implements Runnable {
// Insert into queue // Insert into queue
carQueue.put(c); carQueue.put(c);
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
print("Interrupted: ChassisBuilder"); print("Interrupted: ChassisBuilder");
} }
print("ChassisBuilder off"); print("ChassisBuilder off");
@@ -52,16 +78,25 @@ class Assembler implements Runnable {
private Car car; private Car car;
private CyclicBarrier barrier = new CyclicBarrier(4); private CyclicBarrier barrier = new CyclicBarrier(4);
private RobotPool robotPool; private RobotPool robotPool;
public Assembler(CarQueue cq, CarQueue fq, RobotPool rp){
public Assembler(CarQueue cq, CarQueue fq, RobotPool rp) {
chassisQueue = cq; chassisQueue = cq;
finishingQueue = fq; finishingQueue = fq;
robotPool = rp; robotPool = rp;
} }
public Car car() { return car; }
public CyclicBarrier barrier() { return barrier; } public Car car() {
return car;
}
public CyclicBarrier barrier() {
return barrier;
}
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
// Blocks until chassis is available: // Blocks until chassis is available:
car = chassisQueue.take(); car = chassisQueue.take();
// Hire robots to perform work: // Hire robots to perform work:
@@ -72,9 +107,9 @@ class Assembler implements Runnable {
// Put car into finishingQueue for further work // Put car into finishingQueue for further work
finishingQueue.put(car); finishingQueue.put(car);
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
print("Exiting Assembler via interrupt"); print("Exiting Assembler via interrupt");
} catch(BrokenBarrierException e) { } catch (BrokenBarrierException e) {
// This one we want to know about // This one we want to know about
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -84,13 +119,18 @@ class Assembler implements Runnable {
class Reporter implements Runnable { class Reporter implements Runnable {
private CarQueue carQueue; private CarQueue carQueue;
public Reporter(CarQueue cq) { carQueue = cq; }
public Reporter(CarQueue cq) {
carQueue = cq;
}
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
print(carQueue.take()); print(carQueue.take());
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
print("Exiting Reporter via interrupt"); print("Exiting Reporter via interrupt");
} }
print("Reporter off"); print("Reporter off");
@@ -99,52 +139,71 @@ class Reporter implements Runnable {
abstract class Robot implements Runnable { abstract class Robot implements Runnable {
private RobotPool pool; private RobotPool pool;
public Robot(RobotPool p) { pool = p; }
public Robot(RobotPool p) {
pool = p;
}
protected Assembler assembler; protected Assembler assembler;
public Robot assignAssembler(Assembler assembler) { public Robot assignAssembler(Assembler assembler) {
this.assembler = assembler; this.assembler = assembler;
return this; return this;
} }
private boolean engage = false; private boolean engage = false;
public synchronized void engage() { public synchronized void engage() {
engage = true; engage = true;
notifyAll(); notifyAll();
} }
// The part of run() that's different for each robot: // The part of run() that's different for each robot:
abstract protected void performService(); abstract protected void performService();
@Override
public void run() { public void run() {
try { try {
powerDown(); // Wait until needed powerDown(); // Wait until needed
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
performService(); performService();
assembler.barrier().await(); // Synchronize assembler.barrier().await(); // Synchronize
// We're done with that job... // We're done with that job...
powerDown(); powerDown();
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
print("Exiting " + this + " via interrupt"); print("Exiting " + this + " via interrupt");
} catch(BrokenBarrierException e) { } catch (BrokenBarrierException e) {
// This one we want to know about // This one we want to know about
throw new RuntimeException(e); throw new RuntimeException(e);
} }
print(this + " off"); print(this + " off");
} }
private synchronized void private synchronized void
powerDown() throws InterruptedException { powerDown() throws InterruptedException {
engage = false; engage = false;
assembler = null; // Disconnect from the Assembler assembler = null; // Disconnect from the Assembler
// Put ourselves back in the available pool: // Put ourselves back in the available pool:
pool.release(this); pool.release(this);
while(engage == false) // Power down while (engage == false) // Power down
{ {
wait(); wait();
} }
} }
public String toString() { return getClass().getName(); }
@Override
public String toString() {
return getClass().getName();
}
} }
class EngineRobot extends Robot { class EngineRobot extends Robot {
public EngineRobot(RobotPool pool) { super(pool); } public EngineRobot(RobotPool pool) {
super(pool);
}
@Override
protected void performService() { protected void performService() {
print(this + " installing engine"); print(this + " installing engine");
assembler.car().addEngine(); assembler.car().addEngine();
@@ -152,7 +211,11 @@ class EngineRobot extends Robot {
} }
class DriveTrainRobot extends Robot { class DriveTrainRobot extends Robot {
public DriveTrainRobot(RobotPool pool) { super(pool); } public DriveTrainRobot(RobotPool pool) {
super(pool);
}
@Override
protected void performService() { protected void performService() {
print(this + " installing DriveTrain"); print(this + " installing DriveTrain");
assembler.car().addDriveTrain(); assembler.car().addDriveTrain();
@@ -160,7 +223,11 @@ class DriveTrainRobot extends Robot {
} }
class WheelRobot extends Robot { class WheelRobot extends Robot {
public WheelRobot(RobotPool pool) { super(pool); } public WheelRobot(RobotPool pool) {
super(pool);
}
@Override
protected void performService() { protected void performService() {
print(this + " installing Wheels"); print(this + " installing Wheels");
assembler.car().addWheels(); assembler.car().addWheels();
@@ -170,15 +237,17 @@ class WheelRobot extends Robot {
class RobotPool { class RobotPool {
// Quietly prevents identical entries: // Quietly prevents identical entries:
private Set<Robot> pool = new HashSet<Robot>(); private Set<Robot> pool = new HashSet<Robot>();
public synchronized void add(Robot r) { public synchronized void add(Robot r) {
pool.add(r); pool.add(r);
notifyAll(); notifyAll();
} }
public synchronized void public synchronized void
hire(Class<? extends Robot> robotType, Assembler d) hire(Class<? extends Robot> robotType, Assembler d)
throws InterruptedException { throws InterruptedException {
for(Robot r : pool) { for (Robot r : pool) {
if(r.getClass().equals(robotType)) { if (r.getClass().equals(robotType)) {
pool.remove(r); pool.remove(r);
r.assignAssembler(d); r.assignAssembler(d);
r.engage(); // Power it up to do the task r.engage(); // Power it up to do the task
@@ -188,7 +257,10 @@ class RobotPool {
wait(); // None available wait(); // None available
hire(robotType, d); // Try again, recursively hire(robotType, d); // Try again, recursively
} }
public synchronized void release(Robot r) { add(r); }
public synchronized void release(Robot r) {
add(r);
}
} }
public class CarBuilder { public class CarBuilder {

View File

@@ -3,13 +3,14 @@ package concurrency;//: concurrency/Chopstick.java
public class Chopstick { public class Chopstick {
private boolean taken = false; private boolean taken = false;
public synchronized
void take() throws InterruptedException { public synchronized void take() throws InterruptedException {
while(taken) { while (taken) {
wait(); wait();
} }
taken = true; taken = true;
} }
public synchronized void drop() { public synchronized void drop() {
taken = false; taken = false;
notifyAll(); notifyAll();

View File

@@ -2,9 +2,11 @@ package concurrency;//: concurrency/CloseResource.java
// Interrupting a blocked task by // Interrupting a blocked task by
// closing the underlying resource. // closing the underlying resource.
// {RunByHand} // {RunByHand}
import java.net.*; import java.net.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.io.*; import java.io.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class CloseResource { public class CloseResource {

View File

@@ -1,6 +1,8 @@
package concurrency;//: concurrency/CountDownLatchDemo.java package concurrency;//: concurrency/CountDownLatchDemo.java
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
// Performs some portion of a task: // Performs some portion of a task:
@@ -9,21 +11,27 @@ class TaskPortion implements Runnable {
private final int id = counter++; private final int id = counter++;
private static Random rand = new Random(47); private static Random rand = new Random(47);
private final CountDownLatch latch; private final CountDownLatch latch;
TaskPortion(CountDownLatch latch) { TaskPortion(CountDownLatch latch) {
this.latch = latch; this.latch = latch;
} }
@Override
public void run() { public void run() {
try { try {
doWork(); doWork();
latch.countDown(); latch.countDown();
} catch(InterruptedException ex) { } catch (InterruptedException ex) {
// Acceptable way to exit // Acceptable way to exit
} }
} }
public void doWork() throws InterruptedException { public void doWork() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(rand.nextInt(2000)); TimeUnit.MILLISECONDS.sleep(rand.nextInt(2000));
print(this + "completed"); print(this + "completed");
} }
@Override
public String toString() { public String toString() {
return String.format("%1$-3d ", id); return String.format("%1$-3d ", id);
} }
@@ -34,17 +42,22 @@ class WaitingTask implements Runnable {
private static int counter = 0; private static int counter = 0;
private final int id = counter++; private final int id = counter++;
private final CountDownLatch latch; private final CountDownLatch latch;
WaitingTask(CountDownLatch latch) { WaitingTask(CountDownLatch latch) {
this.latch = latch; this.latch = latch;
} }
@Override
public void run() { public void run() {
try { try {
latch.await(); latch.await();
print("Latch barrier passed for " + this); print("Latch barrier passed for " + this);
} catch(InterruptedException ex) { } catch (InterruptedException ex) {
print(this + " interrupted"); print(this + " interrupted");
} }
} }
@Override
public String toString() { public String toString() {
return String.format("WaitingTask %1$-3d ", id); return String.format("WaitingTask %1$-3d ", id);
} }
@@ -52,14 +65,15 @@ class WaitingTask implements Runnable {
public class CountDownLatchDemo { public class CountDownLatchDemo {
static final int SIZE = 100; static final int SIZE = 100;
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
// All must share a single CountDownLatch object: // All must share a single CountDownLatch object:
CountDownLatch latch = new CountDownLatch(SIZE); CountDownLatch latch = new CountDownLatch(SIZE);
for(int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
exec.execute(new WaitingTask(latch)); exec.execute(new WaitingTask(latch));
} }
for(int i = 0; i < SIZE; i++) { for (int i = 0; i < SIZE; i++) {
exec.execute(new TaskPortion(latch)); exec.execute(new TaskPortion(latch));
} }
print("Launched all tasks"); print("Launched all tasks");

View File

@@ -3,33 +3,54 @@
// demonstrates protection of a non-thread-safe class // demonstrates protection of a non-thread-safe class
// with a thread-safe one. // with a thread-safe one.
package concurrency; package concurrency;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
import java.util.*; import java.util.*;
class Pair { // Not thread-safe class Pair { // Not thread-safe
private int x, y; private int x, y;
public Pair(int x, int y) { public Pair(int x, int y) {
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
public Pair() { this(0, 0); }
public int getX() { return x; } public Pair() {
public int getY() { return y; } this(0, 0);
public void incrementX() { x++; } }
public void incrementY() { y++; }
public int getX() {
return x;
}
public int getY() {
return y;
}
public void incrementX() {
x++;
}
public void incrementY() {
y++;
}
@Override
public String toString() { public String toString() {
return "x: " + x + ", y: " + y; return "x: " + x + ", y: " + y;
} }
public class PairValuesNotEqualException public class PairValuesNotEqualException
extends RuntimeException { extends RuntimeException {
public PairValuesNotEqualException() { public PairValuesNotEqualException() {
super("Pair values not equal: " + Pair.this); super("Pair values not equal: " + Pair.this);
} }
} }
// Arbitrary invariant -- both variables must be equal: // Arbitrary invariant -- both variables must be equal:
public void checkState() { public void checkState() {
if(x != y) { if (x != y) {
throw new PairValuesNotEqualException(); throw new PairValuesNotEqualException();
} }
} }
@@ -41,22 +62,27 @@ abstract class PairManager {
protected Pair p = new Pair(); protected Pair p = new Pair();
private List<Pair> storage = private List<Pair> storage =
Collections.synchronizedList(new ArrayList<Pair>()); Collections.synchronizedList(new ArrayList<Pair>());
public synchronized Pair getPair() { public synchronized Pair getPair() {
// Make a copy to keep the original safe: // Make a copy to keep the original safe:
return new Pair(p.getX(), p.getY()); return new Pair(p.getX(), p.getY());
} }
// Assume this is a time consuming operation // Assume this is a time consuming operation
protected void store(Pair p) { protected void store(Pair p) {
storage.add(p); storage.add(p);
try { try {
TimeUnit.MILLISECONDS.sleep(50); TimeUnit.MILLISECONDS.sleep(50);
} catch(InterruptedException ignore) {} } catch (InterruptedException ignore) {
} }
}
public abstract void increment(); public abstract void increment();
} }
// Synchronize the entire method: // Synchronize the entire method:
class PairManager1 extends PairManager { class PairManager1 extends PairManager {
@Override
public synchronized void increment() { public synchronized void increment() {
p.incrementX(); p.incrementX();
p.incrementY(); p.incrementY();
@@ -66,9 +92,10 @@ class PairManager1 extends PairManager {
// Use a critical section: // Use a critical section:
class PairManager2 extends PairManager { class PairManager2 extends PairManager {
@Override
public void increment() { public void increment() {
Pair temp; Pair temp;
synchronized(this) { synchronized (this) {
p.incrementX(); p.incrementX();
p.incrementY(); p.incrementY();
temp = getPair(); temp = getPair();
@@ -79,14 +106,19 @@ class PairManager2 extends PairManager {
class PairManipulator implements Runnable { class PairManipulator implements Runnable {
private PairManager pm; private PairManager pm;
public PairManipulator(PairManager pm) { public PairManipulator(PairManager pm) {
this.pm = pm; this.pm = pm;
} }
@Override
public void run() { public void run() {
while(true) { while (true) {
pm.increment(); pm.increment();
} }
} }
@Override
public String toString() { public String toString() {
return "Pair: " + pm.getPair() + return "Pair: " + pm.getPair() +
" checkCounter = " + pm.checkCounter.get(); " checkCounter = " + pm.checkCounter.get();
@@ -95,11 +127,14 @@ class PairManipulator implements Runnable {
class PairChecker implements Runnable { class PairChecker implements Runnable {
private PairManager pm; private PairManager pm;
public PairChecker(PairManager pm) { public PairChecker(PairManager pm) {
this.pm = pm; this.pm = pm;
} }
@Override
public void run() { public void run() {
while(true) { while (true) {
pm.checkCounter.incrementAndGet(); pm.checkCounter.incrementAndGet();
pm.getPair().checkState(); pm.getPair().checkState();
} }
@@ -123,12 +158,13 @@ public class CriticalSection {
exec.execute(pcheck2); exec.execute(pcheck2);
try { try {
TimeUnit.MILLISECONDS.sleep(500); TimeUnit.MILLISECONDS.sleep(500);
} catch(InterruptedException e) { } catch (InterruptedException e) {
System.out.println("Sleep interrupted"); System.out.println("Sleep interrupted");
} }
System.out.println("pm1: " + pm1 + "\npm2: " + pm2); System.out.println("pm1: " + pm1 + "\npm2: " + pm2);
System.exit(0); System.exit(0);
} }
public static void main(String[] args) { public static void main(String[] args) {
PairManager PairManager
pman1 = new PairManager1(), pman1 = new PairManager1(),

View File

@@ -1,24 +1,29 @@
package concurrency;//: concurrency/DaemonFromFactory.java package concurrency;//: concurrency/DaemonFromFactory.java
// Using a Thread Factory to create daemons. // Using a Thread Factory to create daemons.
import java.util.concurrent.*; import java.util.concurrent.*;
import net.mindview.util.*; import net.mindview.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class DaemonFromFactory implements Runnable { public class DaemonFromFactory implements Runnable {
@Override
public void run() { public void run() {
try { try {
while(true) { while (true) {
TimeUnit.MILLISECONDS.sleep(100); TimeUnit.MILLISECONDS.sleep(100);
print(Thread.currentThread() + " " + this); print(Thread.currentThread() + " " + this);
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
print("Interrupted"); print("Interrupted");
} }
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool( ExecutorService exec = Executors.newCachedThreadPool(
new DaemonThreadFactory()); new DaemonThreadFactory());
for(int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
exec.execute(new DaemonFromFactory()); exec.execute(new DaemonFromFactory());
} }
print("All daemons started"); print("All daemons started");

View File

@@ -1,29 +1,34 @@
package concurrency;//: concurrency/Daemons.java package concurrency;//: concurrency/Daemons.java
// Daemon threads spawn other daemon threads. // Daemon threads spawn other daemon threads.
import java.util.concurrent.*; import java.util.concurrent.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
class Daemon implements Runnable { class Daemon implements Runnable {
private Thread[] t = new Thread[10]; private Thread[] t = new Thread[10];
@Override
public void run() { public void run() {
for(int i = 0; i < t.length; i++) { for (int i = 0; i < t.length; i++) {
t[i] = new Thread(new DaemonSpawn()); t[i] = new Thread(new DaemonSpawn());
t[i].start(); t[i].start();
printnb("DaemonSpawn " + i + " started, "); printnb("DaemonSpawn " + i + " started, ");
} }
for(int i = 0; i < t.length; i++) { for (int i = 0; i < t.length; i++) {
printnb("t[" + i + "].isDaemon() = " + printnb("t[" + i + "].isDaemon() = " +
t[i].isDaemon() + ", "); t[i].isDaemon() + ", ");
} }
while(true) { while (true) {
Thread.yield(); Thread.yield();
} }
} }
} }
class DaemonSpawn implements Runnable { class DaemonSpawn implements Runnable {
@Override
public void run() { public void run() {
while(true) { while (true) {
Thread.yield(); Thread.yield();
} }
} }

View File

@@ -1,14 +1,17 @@
package concurrency;//: concurrency/DaemonsDontRunFinally.java package concurrency;//: concurrency/DaemonsDontRunFinally.java
// Daemon threads don't run the finally clause // Daemon threads don't run the finally clause
import java.util.concurrent.*; import java.util.concurrent.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
class ADaemon implements Runnable { class ADaemon implements Runnable {
@Override
public void run() { public void run() {
try { try {
print("Starting ADaemon"); print("Starting ADaemon");
TimeUnit.SECONDS.sleep(1); TimeUnit.SECONDS.sleep(1);
} catch(InterruptedException e) { } catch (InterruptedException e) {
print("Exiting via InterruptedException"); print("Exiting via InterruptedException");
} finally { } finally {
print("This should always run?"); print("This should always run?");

View File

@@ -1,28 +1,29 @@
package concurrency;//: concurrency/DeadlockingDiningPhilosophers.java package concurrency;//: concurrency/DeadlockingDiningPhilosophers.java
// Demonstrates how deadlock can be hidden in a program. // Demonstrates how deadlock can be hidden in a program.
// {Args: 0 5 timeout} // {Args: 0 5 timeout}
import java.util.concurrent.*; import java.util.concurrent.*;
public class DeadlockingDiningPhilosophers { public class DeadlockingDiningPhilosophers {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
int ponder = 5; int ponder = 5;
if(args.length > 0) { if (args.length > 0) {
ponder = Integer.parseInt(args[0]); ponder = Integer.parseInt(args[0]);
} }
int size = 5; int size = 5;
if(args.length > 1) { if (args.length > 1) {
size = Integer.parseInt(args[1]); size = Integer.parseInt(args[1]);
} }
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
Chopstick[] sticks = new Chopstick[size]; Chopstick[] sticks = new Chopstick[size];
for(int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
sticks[i] = new Chopstick(); sticks[i] = new Chopstick();
} }
for(int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
exec.execute(new Philosopher( exec.execute(new Philosopher(
sticks[i], sticks[(i+1) % size], i, ponder)); sticks[i], sticks[(i + 1) % size], i, ponder));
} }
if(args.length == 3 && args[2].equals("timeout")) { if (args.length == 3 && args[2].equals("timeout")) {
TimeUnit.SECONDS.sleep(5); TimeUnit.SECONDS.sleep(5);
} else { } else {
System.out.println("Press 'Enter' to quit"); System.out.println("Press 'Enter' to quit");

View File

@@ -1,6 +1,8 @@
package concurrency;//: concurrency/DelayQueueDemo.java package concurrency;//: concurrency/DelayQueueDemo.java
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.*; import java.util.*;
import static java.util.concurrent.TimeUnit.*; import static java.util.concurrent.TimeUnit.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
@@ -11,42 +13,58 @@ class DelayedTask implements Runnable, Delayed {
private final long trigger; private final long trigger;
protected static List<DelayedTask> sequence = protected static List<DelayedTask> sequence =
new ArrayList<DelayedTask>(); new ArrayList<DelayedTask>();
public DelayedTask(int delayInMilliseconds) { public DelayedTask(int delayInMilliseconds) {
delta = delayInMilliseconds; delta = delayInMilliseconds;
trigger = System.nanoTime() + trigger = System.nanoTime() +
NANOSECONDS.convert(delta, MILLISECONDS); NANOSECONDS.convert(delta, MILLISECONDS);
sequence.add(this); sequence.add(this);
} }
@Override
public long getDelay(TimeUnit unit) { public long getDelay(TimeUnit unit) {
return unit.convert( return unit.convert(
trigger - System.nanoTime(), NANOSECONDS); trigger - System.nanoTime(), NANOSECONDS);
} }
@Override
public int compareTo(Delayed arg) { public int compareTo(Delayed arg) {
DelayedTask that = (DelayedTask)arg; DelayedTask that = (DelayedTask) arg;
if(trigger < that.trigger) { if (trigger < that.trigger) {
return -1; return -1;
} }
if(trigger > that.trigger) { if (trigger > that.trigger) {
return 1; return 1;
} }
return 0; return 0;
} }
public void run() { printnb(this + " "); }
@Override
public void run() {
printnb(this + " ");
}
@Override
public String toString() { public String toString() {
return String.format("[%1$-4d]", delta) + return String.format("[%1$-4d]", delta) +
" Task " + id; " Task " + id;
} }
public String summary() { public String summary() {
return "(" + id + ":" + delta + ")"; return "(" + id + ":" + delta + ")";
} }
public static class EndSentinel extends DelayedTask { public static class EndSentinel extends DelayedTask {
private ExecutorService exec; private ExecutorService exec;
public EndSentinel(int delay, ExecutorService e) { public EndSentinel(int delay, ExecutorService e) {
super(delay); super(delay);
exec = e; exec = e;
} }
@Override
public void run() { public void run() {
for(DelayedTask pt : sequence) { for (DelayedTask pt : sequence) {
printnb(pt.summary() + " "); printnb(pt.summary() + " ");
} }
print(); print();
@@ -58,15 +76,18 @@ class DelayedTask implements Runnable, Delayed {
class DelayedTaskConsumer implements Runnable { class DelayedTaskConsumer implements Runnable {
private DelayQueue<DelayedTask> q; private DelayQueue<DelayedTask> q;
public DelayedTaskConsumer(DelayQueue<DelayedTask> q) { public DelayedTaskConsumer(DelayQueue<DelayedTask> q) {
this.q = q; this.q = q;
} }
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
q.take().run(); // Run task with the current thread q.take().run(); // Run task with the current thread
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
// Acceptable way to exit // Acceptable way to exit
} }
print("Finished DelayedTaskConsumer"); print("Finished DelayedTaskConsumer");
@@ -80,7 +101,7 @@ public class DelayQueueDemo {
DelayQueue<DelayedTask> queue = DelayQueue<DelayedTask> queue =
new DelayQueue<DelayedTask>(); new DelayQueue<DelayedTask>();
// Fill with tasks that have random delays: // Fill with tasks that have random delays:
for(int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
queue.put(new DelayedTask(rand.nextInt(5000))); queue.put(new DelayedTask(rand.nextInt(5000)));
} }
// Set the stopping point // Set the stopping point

View File

@@ -1,31 +1,37 @@
package concurrency;//: concurrency/EvenChecker.java package concurrency;//: concurrency/EvenChecker.java
import java.util.concurrent.*; import java.util.concurrent.*;
public class EvenChecker implements Runnable { public class EvenChecker implements Runnable {
private IntGenerator generator; private IntGenerator generator;
private final int id; private final int id;
public EvenChecker(IntGenerator g, int ident) { public EvenChecker(IntGenerator g, int ident) {
generator = g; generator = g;
id = ident; id = ident;
} }
@Override
public void run() { public void run() {
while(!generator.isCanceled()) { while (!generator.isCanceled()) {
int val = generator.next(); int val = generator.next();
if(val % 2 != 0) { if (val % 2 != 0) {
System.out.println(val + " not even!"); System.out.println(val + " not even!");
generator.cancel(); // Cancels all EvenCheckers generator.cancel(); // Cancels all EvenCheckers
} }
} }
} }
// Test any type of IntGenerator: // Test any type of IntGenerator:
public static void test(IntGenerator gp, int count) { public static void test(IntGenerator gp, int count) {
System.out.println("Press Control-C to exit"); System.out.println("Press Control-C to exit");
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
exec.execute(new EvenChecker(gp, i)); exec.execute(new EvenChecker(gp, i));
} }
exec.shutdown(); exec.shutdown();
} }
// Default value for count: // Default value for count:
public static void test(IntGenerator gp) { public static void test(IntGenerator gp) {
test(gp, 10); test(gp, 10);

View File

@@ -3,11 +3,14 @@ package concurrency;//: concurrency/EvenGenerator.java
public class EvenGenerator extends IntGenerator { public class EvenGenerator extends IntGenerator {
private int currentEvenValue = 0; private int currentEvenValue = 0;
@Override
public int next() { public int next() {
++currentEvenValue; // Danger point here! ++currentEvenValue; // Danger point here!
++currentEvenValue; ++currentEvenValue;
return currentEvenValue; return currentEvenValue;
} }
public static void main(String[] args) { public static void main(String[] args) {
EvenChecker.test(new EvenGenerator()); EvenChecker.test(new EvenGenerator());
} }

View File

@@ -1,11 +1,14 @@
package concurrency;//: concurrency/ExceptionThread.java package concurrency;//: concurrency/ExceptionThread.java
// {ThrowsException} // {ThrowsException}
import java.util.concurrent.*; import java.util.concurrent.*;
public class ExceptionThread implements Runnable { public class ExceptionThread implements Runnable {
@Override
public void run() { public void run() {
throw new RuntimeException(); throw new RuntimeException();
} }
public static void main(String[] args) { public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExceptionThread()); exec.execute(new ExceptionThread());

View File

@@ -1,28 +1,33 @@
package concurrency;//: concurrency/ExchangerDemo.java package concurrency;//: concurrency/ExchangerDemo.java
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.*; import java.util.*;
import net.mindview.util.*; import net.mindview.util.*;
class ExchangerProducer<T> implements Runnable { class ExchangerProducer<T> implements Runnable {
private Generator<T> generator; private Generator<T> generator;
private Exchanger<List<T>> exchanger; private Exchanger<List<T>> exchanger;
private List<T> holder; private List<T> holder;
ExchangerProducer(Exchanger<List<T>> exchg, ExchangerProducer(Exchanger<List<T>> exchg,
Generator<T> gen, List<T> holder) { Generator<T> gen, List<T> holder) {
exchanger = exchg; exchanger = exchg;
generator = gen; generator = gen;
this.holder = holder; this.holder = holder;
} }
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
for(int i = 0; i < ExchangerDemo.size; i++) { for (int i = 0; i < ExchangerDemo.size; i++) {
holder.add(generator.next()); holder.add(generator.next());
} }
// Exchange full for empty: // Exchange full for empty:
holder = exchanger.exchange(holder); holder = exchanger.exchange(holder);
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
// OK to terminate this way. // OK to terminate this way.
} }
} }
@@ -32,20 +37,23 @@ class ExchangerConsumer<T> implements Runnable {
private Exchanger<List<T>> exchanger; private Exchanger<List<T>> exchanger;
private List<T> holder; private List<T> holder;
private volatile T value; private volatile T value;
ExchangerConsumer(Exchanger<List<T>> ex, List<T> holder){
ExchangerConsumer(Exchanger<List<T>> ex, List<T> holder) {
exchanger = ex; exchanger = ex;
this.holder = holder; this.holder = holder;
} }
@Override
public void run() { public void run() {
try { try {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
holder = exchanger.exchange(holder); holder = exchanger.exchange(holder);
for(T x : holder) { for (T x : holder) {
value = x; // Fetch out value value = x; // Fetch out value
holder.remove(x); // OK for CopyOnWriteArrayList holder.remove(x); // OK for CopyOnWriteArrayList
} }
} }
} catch(InterruptedException e) { } catch (InterruptedException e) {
// OK to terminate this way. // OK to terminate this way.
} }
System.out.println("Final value: " + value); System.out.println("Final value: " + value);
@@ -55,11 +63,12 @@ class ExchangerConsumer<T> implements Runnable {
public class ExchangerDemo { public class ExchangerDemo {
static int size = 10; static int size = 10;
static int delay = 5; // Seconds static int delay = 5; // Seconds
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
if(args.length > 0) { if (args.length > 0) {
size = new Integer(args[0]); size = new Integer(args[0]);
} }
if(args.length > 1) { if (args.length > 1) {
delay = new Integer(args[1]); delay = new Integer(args[1]);
} }
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
@@ -70,7 +79,7 @@ public class ExchangerDemo {
exec.execute(new ExchangerProducer<Fat>(xc, exec.execute(new ExchangerProducer<Fat>(xc,
BasicGenerator.create(Fat.class), producerList)); BasicGenerator.create(Fat.class), producerList));
exec.execute( exec.execute(
new ExchangerConsumer<Fat>(xc,consumerList)); new ExchangerConsumer<Fat>(xc, consumerList));
TimeUnit.SECONDS.sleep(delay); TimeUnit.SECONDS.sleep(delay);
exec.shutdownNow(); exec.shutdownNow();
} }

View File

@@ -1,11 +1,14 @@
//: concurrency/ExplicitCriticalSection.java //: concurrency/ExplicitCriticalSection.java
// Using explicit Lock objects to create critical sections. // Using explicit Lock objects to create critical sections.
package concurrency; package concurrency;
import java.util.concurrent.locks.*; import java.util.concurrent.locks.*;
// Synchronize the entire method: // Synchronize the entire method:
class ExplicitPairManager1 extends PairManager { class ExplicitPairManager1 extends PairManager {
private Lock lock = new ReentrantLock(); private Lock lock = new ReentrantLock();
@Override
public synchronized void increment() { public synchronized void increment() {
lock.lock(); lock.lock();
try { try {
@@ -21,6 +24,8 @@ class ExplicitPairManager1 extends PairManager {
// Use a critical section: // Use a critical section:
class ExplicitPairManager2 extends PairManager { class ExplicitPairManager2 extends PairManager {
private Lock lock = new ReentrantLock(); private Lock lock = new ReentrantLock();
@Override
public void increment() { public void increment() {
Pair temp; Pair temp;
lock.lock(); lock.lock();

View File

@@ -1,7 +1,9 @@
package concurrency;//: concurrency/FastSimulation.java package concurrency;//: concurrency/FastSimulation.java
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
import java.util.*; import java.util.*;
import static net.mindview.util.Print.*; import static net.mindview.util.Print.*;
public class FastSimulation { public class FastSimulation {
@@ -11,18 +13,20 @@ public class FastSimulation {
static final AtomicInteger[][] GRID = static final AtomicInteger[][] GRID =
new AtomicInteger[N_ELEMENTS][N_GENES]; new AtomicInteger[N_ELEMENTS][N_GENES];
static Random rand = new Random(47); static Random rand = new Random(47);
static class Evolver implements Runnable { static class Evolver implements Runnable {
@Override
public void run() { public void run() {
while(!Thread.interrupted()) { while (!Thread.interrupted()) {
// Randomly select an element to work on: // Randomly select an element to work on:
int element = rand.nextInt(N_ELEMENTS); int element = rand.nextInt(N_ELEMENTS);
for(int i = 0; i < N_GENES; i++) { for (int i = 0; i < N_GENES; i++) {
int previous = element - 1; int previous = element - 1;
if(previous < 0) { if (previous < 0) {
previous = N_ELEMENTS - 1; previous = N_ELEMENTS - 1;
} }
int next = element + 1; int next = element + 1;
if(next >= N_ELEMENTS) { if (next >= N_ELEMENTS) {
next = 0; next = 0;
} }
int oldvalue = GRID[element][i].get(); int oldvalue = GRID[element][i].get();
@@ -30,7 +34,7 @@ public class FastSimulation {
int newvalue = oldvalue + int newvalue = oldvalue +
GRID[previous][i].get() + GRID[next][i].get(); GRID[previous][i].get() + GRID[next][i].get();
newvalue /= 3; // Average the three values newvalue /= 3; // Average the three values
if(!GRID[element][i] if (!GRID[element][i]
.compareAndSet(oldvalue, newvalue)) { .compareAndSet(oldvalue, newvalue)) {
// Policy here to deal with failure. Here, we // Policy here to deal with failure. Here, we
// just report it and ignore it; our model // just report it and ignore it; our model
@@ -41,14 +45,15 @@ public class FastSimulation {
} }
} }
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < N_ELEMENTS; i++) { for (int i = 0; i < N_ELEMENTS; i++) {
for(int j = 0; j < N_GENES; j++) { for (int j = 0; j < N_GENES; j++) {
GRID[i][j] = new AtomicInteger(rand.nextInt(1000)); GRID[i][j] = new AtomicInteger(rand.nextInt(1000));
} }
} }
for(int i = 0; i < N_EVOLVERS; i++) { for (int i = 0; i < N_EVOLVERS; i++) {
exec.execute(new Evolver()); exec.execute(new Evolver());
} }
TimeUnit.SECONDS.sleep(5); TimeUnit.SECONDS.sleep(5);

View File

@@ -5,12 +5,20 @@ public class Fat {
private volatile double d; // Prevent optimization private volatile double d; // Prevent optimization
private static int counter = 0; private static int counter = 0;
private final int id = counter++; private final int id = counter++;
public Fat() { public Fat() {
// Expensive, interruptible operation: // Expensive, interruptible operation:
for(int i = 1; i < 10000; i++) { for (int i = 1; i < 10000; i++) {
d += (Math.PI + Math.E) / (double)i; d += (Math.PI + Math.E) / (double) i;
} }
} }
public void operation() { System.out.println(this); }
public String toString() { return "Fat id: " + id; } public void operation() {
System.out.println(this);
}
@Override
public String toString() {
return "Fat id: " + id;
}
} ///:~ } ///:~

View File

@@ -1,25 +1,26 @@
package concurrency;//: concurrency/FixedDiningPhilosophers.java package concurrency;//: concurrency/FixedDiningPhilosophers.java
// Dining philosophers without deadlock. // Dining philosophers without deadlock.
// {Args: 5 5 timeout} // {Args: 5 5 timeout}
import java.util.concurrent.*; import java.util.concurrent.*;
public class FixedDiningPhilosophers { public class FixedDiningPhilosophers {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
int ponder = 5; int ponder = 5;
if(args.length > 0) { if (args.length > 0) {
ponder = Integer.parseInt(args[0]); ponder = Integer.parseInt(args[0]);
} }
int size = 5; int size = 5;
if(args.length > 1) { if (args.length > 1) {
size = Integer.parseInt(args[1]); size = Integer.parseInt(args[1]);
} }
ExecutorService exec = Executors.newCachedThreadPool(); ExecutorService exec = Executors.newCachedThreadPool();
Chopstick[] sticks = new Chopstick[size]; Chopstick[] sticks = new Chopstick[size];
for(int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
sticks[i] = new Chopstick(); sticks[i] = new Chopstick();
} }
for(int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
if(i < (size-1)) { if (i < (size - 1)) {
exec.execute(new Philosopher( exec.execute(new Philosopher(
sticks[i], sticks[i + 1], i, ponder)); sticks[i], sticks[i + 1], i, ponder));
} else { } else {
@@ -27,7 +28,7 @@ public class FixedDiningPhilosophers {
sticks[0], sticks[i], i, ponder)); sticks[0], sticks[i], i, ponder));
} }
} }
if(args.length == 3 && args[2].equals("timeout")) { if (args.length == 3 && args[2].equals("timeout")) {
TimeUnit.SECONDS.sleep(5); TimeUnit.SECONDS.sleep(5);
} else { } else {
System.out.println("Press 'Enter' to quit"); System.out.println("Press 'Enter' to quit");

View File

@@ -1,11 +1,12 @@
package concurrency;//: concurrency/FixedThreadPool.java package concurrency;//: concurrency/FixedThreadPool.java
import java.util.concurrent.*; import java.util.concurrent.*;
public class FixedThreadPool { public class FixedThreadPool {
public static void main(String[] args) { public static void main(String[] args) {
// Constructor argument is number of threads: // Constructor argument is number of threads:
ExecutorService exec = Executors.newFixedThreadPool(5); ExecutorService exec = Executors.newFixedThreadPool(5);
for(int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
exec.execute(new LiftOff()); exec.execute(new LiftOff());
} }
exec.shutdown(); exec.shutdown();

View File

@@ -2,6 +2,7 @@ package concurrency;//: concurrency/GreenhouseScheduler.java
// Rewriting innerclasses/GreenhouseController.java // Rewriting innerclasses/GreenhouseController.java
// to use a ScheduledThreadPoolExecutor. // to use a ScheduledThreadPoolExecutor.
// {Args: 5000} // {Args: 5000}
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.*; import java.util.*;
@@ -9,23 +10,30 @@ public class GreenhouseScheduler {
private volatile boolean light = false; private volatile boolean light = false;
private volatile boolean water = false; private volatile boolean water = false;
private String thermostat = "Day"; private String thermostat = "Day";
public synchronized String getThermostat() { public synchronized String getThermostat() {
return thermostat; return thermostat;
} }
public synchronized void setThermostat(String value) { public synchronized void setThermostat(String value) {
thermostat = value; thermostat = value;
} }
ScheduledThreadPoolExecutor scheduler = ScheduledThreadPoolExecutor scheduler =
new ScheduledThreadPoolExecutor(10); new ScheduledThreadPoolExecutor(10);
public void schedule(Runnable event, long delay) { public void schedule(Runnable event, long delay) {
scheduler.schedule(event,delay,TimeUnit.MILLISECONDS); scheduler.schedule(event, delay, TimeUnit.MILLISECONDS);
} }
public void public void
repeat(Runnable event, long initialDelay, long period) { repeat(Runnable event, long initialDelay, long period) {
scheduler.scheduleAtFixedRate( scheduler.scheduleAtFixedRate(
event, initialDelay, period, TimeUnit.MILLISECONDS); event, initialDelay, period, TimeUnit.MILLISECONDS);
} }
class LightOn implements Runnable { class LightOn implements Runnable {
@Override
public void run() { public void run() {
// Put hardware control code here to // Put hardware control code here to
// physically turn on the light. // physically turn on the light.
@@ -33,7 +41,9 @@ public class GreenhouseScheduler {
light = true; light = true;
} }
} }
class LightOff implements Runnable { class LightOff implements Runnable {
@Override
public void run() { public void run() {
// Put hardware control code here to // Put hardware control code here to
// physically turn off the light. // physically turn off the light.
@@ -41,62 +51,81 @@ public class GreenhouseScheduler {
light = false; light = false;
} }
} }
class WaterOn implements Runnable { class WaterOn implements Runnable {
@Override
public void run() { public void run() {
// Put hardware control code here. // Put hardware control code here.
System.out.println("Turning greenhouse water on"); System.out.println("Turning greenhouse water on");
water = true; water = true;
} }
} }
class WaterOff implements Runnable { class WaterOff implements Runnable {
@Override
public void run() { public void run() {
// Put hardware control code here. // Put hardware control code here.
System.out.println("Turning greenhouse water off"); System.out.println("Turning greenhouse water off");
water = false; water = false;
} }
} }
class ThermostatNight implements Runnable { class ThermostatNight implements Runnable {
@Override
public void run() { public void run() {
// Put hardware control code here. // Put hardware control code here.
System.out.println("Thermostat to night setting"); System.out.println("Thermostat to night setting");
setThermostat("Night"); setThermostat("Night");
} }
} }
class ThermostatDay implements Runnable { class ThermostatDay implements Runnable {
@Override
public void run() { public void run() {
// Put hardware control code here. // Put hardware control code here.
System.out.println("Thermostat to day setting"); System.out.println("Thermostat to day setting");
setThermostat("Day"); setThermostat("Day");
} }
} }
class Bell implements Runnable { class Bell implements Runnable {
public void run() { System.out.println("Bing!"); } @Override
public void run() {
System.out.println("Bing!");
} }
}
class Terminate implements Runnable { class Terminate implements Runnable {
@Override
public void run() { public void run() {
System.out.println("Terminating"); System.out.println("Terminating");
scheduler.shutdownNow(); scheduler.shutdownNow();
// Must start a separate task to do this job, // Must start a separate task to do this job,
// since the scheduler has been shut down: // since the scheduler has been shut down:
new Thread() { new Thread() {
@Override
public void run() { public void run() {
for(DataPoint d : data) { for (DataPoint d : data) {
System.out.println(d); System.out.println(d);
} }
} }
}.start(); }.start();
} }
} }
// New feature: data collection // New feature: data collection
static class DataPoint { static class DataPoint {
final Calendar time; final Calendar time;
final float temperature; final float temperature;
final float humidity; final float humidity;
public DataPoint(Calendar d, float temp, float hum) { public DataPoint(Calendar d, float temp, float hum) {
time = d; time = d;
temperature = temp; temperature = temp;
humidity = hum; humidity = hum;
} }
@Override
public String toString() { public String toString() {
return time.getTime() + return time.getTime() +
String.format( String.format(
@@ -104,11 +133,14 @@ public class GreenhouseScheduler {
temperature, humidity); temperature, humidity);
} }
} }
private Calendar lastTime = Calendar.getInstance(); private Calendar lastTime = Calendar.getInstance();
{ // Adjust date to the half hour { // Adjust date to the half hour
lastTime.set(Calendar.MINUTE, 30); lastTime.set(Calendar.MINUTE, 30);
lastTime.set(Calendar.SECOND, 00); lastTime.set(Calendar.SECOND, 00);
} }
private float lastTemp = 65.0f; private float lastTemp = 65.0f;
private int tempDirection = +1; private int tempDirection = +1;
private float lastHumidity = 50.0f; private float lastHumidity = 50.0f;
@@ -116,21 +148,23 @@ public class GreenhouseScheduler {
private Random rand = new Random(47); private Random rand = new Random(47);
List<DataPoint> data = Collections.synchronizedList( List<DataPoint> data = Collections.synchronizedList(
new ArrayList<DataPoint>()); new ArrayList<DataPoint>());
class CollectData implements Runnable { class CollectData implements Runnable {
@Override
public void run() { public void run() {
System.out.println("Collecting data"); System.out.println("Collecting data");
synchronized(GreenhouseScheduler.this) { synchronized (GreenhouseScheduler.this) {
// Pretend the interval is longer than it is: // Pretend the interval is longer than it is:
lastTime.set(Calendar.MINUTE, lastTime.set(Calendar.MINUTE,
lastTime.get(Calendar.MINUTE) + 30); lastTime.get(Calendar.MINUTE) + 30);
// One in 5 chances of reversing the direction: // One in 5 chances of reversing the direction:
if(rand.nextInt(5) == 4) { if (rand.nextInt(5) == 4) {
tempDirection = -tempDirection; tempDirection = -tempDirection;
} }
// Store previous value: // Store previous value:
lastTemp = lastTemp + lastTemp = lastTemp +
tempDirection * (1.0f + rand.nextFloat()); tempDirection * (1.0f + rand.nextFloat());
if(rand.nextInt(5) == 4) { if (rand.nextInt(5) == 4) {
humidityDirection = -humidityDirection; humidityDirection = -humidityDirection;
} }
lastHumidity = lastHumidity + lastHumidity = lastHumidity +
@@ -138,11 +172,12 @@ public class GreenhouseScheduler {
// Calendar must be cloned, otherwise all // Calendar must be cloned, otherwise all
// DataPoints hold references to the same lastTime. // DataPoints hold references to the same lastTime.
// For a basic object like Calendar, clone() is OK. // For a basic object like Calendar, clone() is OK.
data.add(new DataPoint((Calendar)lastTime.clone(), data.add(new DataPoint((Calendar) lastTime.clone(),
lastTemp, lastHumidity)); lastTemp, lastHumidity));
} }
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
GreenhouseScheduler gh = new GreenhouseScheduler(); GreenhouseScheduler gh = new GreenhouseScheduler();
gh.schedule(gh.new Terminate(), 5000); gh.schedule(gh.new Terminate(), 5000);

Some files were not shown because too many files have changed in this diff Show More