格式化代码
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
package access;//: access/ChocolateChip.java
|
||||
// Can't use package-access member from another package.
|
||||
|
||||
import access.dessert.*;
|
||||
|
||||
public class ChocolateChip extends Cookie {
|
||||
public ChocolateChip() {
|
||||
System.out.println("ChocolateChip constructor");
|
||||
}
|
||||
|
||||
public void chomp() {
|
||||
//! bite(); // Can't access bite
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ChocolateChip x = new ChocolateChip();
|
||||
x.chomp();
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package access;//: access/ChocolateChip2.java
|
||||
|
||||
import access.cookie2.*;
|
||||
|
||||
public class ChocolateChip2 extends Cookie {
|
||||
public ChocolateChip2() {
|
||||
System.out.println("ChocolateChip2 constructor");
|
||||
}
|
||||
public void chomp() { bite(); } // Protected method
|
||||
|
||||
public void chomp() {
|
||||
bite();
|
||||
} // Protected method
|
||||
|
||||
public static void main(String[] args) {
|
||||
ChocolateChip2 x = new ChocolateChip2();
|
||||
x.chomp();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package access;//: access/Dinner.java
|
||||
// Uses the library.
|
||||
|
||||
import access.dessert.*;
|
||||
|
||||
public class Dinner {
|
||||
|
||||
@@ -2,7 +2,9 @@ package access;//: access/IceCream.java
|
||||
// Demonstrates "private" keyword.
|
||||
|
||||
class Sundae {
|
||||
private Sundae() {}
|
||||
private Sundae() {
|
||||
}
|
||||
|
||||
static Sundae makeASundae() {
|
||||
return new Sundae();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package access;//: access/ImportedMyClass.java
|
||||
|
||||
import access.mypackage.*;
|
||||
|
||||
public class ImportedMyClass {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package access;//: access/LibTest.java
|
||||
// Uses the library.
|
||||
|
||||
import net.mindview.simple.*;
|
||||
|
||||
public class LibTest {
|
||||
|
||||
@@ -3,7 +3,9 @@ package access;//: access/Lunch.java
|
||||
// effectively private with private constructors:
|
||||
|
||||
class Soup1 {
|
||||
private Soup1() {}
|
||||
private Soup1() {
|
||||
}
|
||||
|
||||
// (1) Allow creation via static method:
|
||||
public static Soup1 makeSoup() {
|
||||
return new Soup1();
|
||||
@@ -11,14 +13,19 @@ class Soup1 {
|
||||
}
|
||||
|
||||
class Soup2 {
|
||||
private Soup2() {}
|
||||
private Soup2() {
|
||||
}
|
||||
|
||||
// (2) Create a static object and return a reference
|
||||
// upon request.(The "Singleton" pattern):
|
||||
private static Soup2 ps1 = new Soup2();
|
||||
|
||||
public static Soup2 access() {
|
||||
return ps1;
|
||||
}
|
||||
public void f() {}
|
||||
|
||||
public void f() {
|
||||
}
|
||||
}
|
||||
|
||||
// Only one public class allowed per file:
|
||||
@@ -27,9 +34,11 @@ public class Lunch {
|
||||
// Can't do this! Private constructor:
|
||||
//! Soup1 soup = new Soup1();
|
||||
}
|
||||
|
||||
void testStatic() {
|
||||
Soup1 soup = Soup1.makeSoup();
|
||||
}
|
||||
|
||||
void testSingleton() {
|
||||
Soup2.access().f();
|
||||
}
|
||||
|
||||
@@ -2,11 +2,17 @@ package access;//: access/OrganizedByAccess.java
|
||||
|
||||
public class OrganizedByAccess {
|
||||
public void pub1() { /* ... */ }
|
||||
|
||||
public void pub2() { /* ... */ }
|
||||
|
||||
public void pub3() { /* ... */ }
|
||||
|
||||
private void priv1() { /* ... */ }
|
||||
|
||||
private void priv2() { /* ... */ }
|
||||
|
||||
private void priv3() { /* ... */ }
|
||||
|
||||
private int i;
|
||||
// ...
|
||||
} ///:~
|
||||
|
||||
@@ -2,5 +2,7 @@ package access;//: access/Pie.java
|
||||
// The other class.
|
||||
|
||||
class Pie {
|
||||
void f() { System.out.println("Pie.f()"); }
|
||||
void f() {
|
||||
System.out.println("Pie.f()");
|
||||
}
|
||||
} ///:~
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package access;//: access/PrintTest.java
|
||||
// Uses the static printing methods in Print.java.
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class PrintTest {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package access;//: access/SingleImport.java
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SingleImport {
|
||||
|
||||
@@ -5,6 +5,7 @@ public class Cookie {
|
||||
public Cookie() {
|
||||
System.out.println("Cookie constructor");
|
||||
}
|
||||
|
||||
protected void bite() {
|
||||
System.out.println("bite");
|
||||
}
|
||||
|
||||
@@ -6,5 +6,8 @@ public class Cookie {
|
||||
public Cookie() {
|
||||
System.out.println("Cookie constructor");
|
||||
}
|
||||
void bite() { System.out.println("bite"); }
|
||||
|
||||
void bite() {
|
||||
System.out.println("bite");
|
||||
}
|
||||
} ///:~
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
//: annotations/AtUnitComposition.java
|
||||
// Creating non-embedded tests.
|
||||
package annotations;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class AtUnitComposition {
|
||||
AtUnitExample1 testObject = new AtUnitExample1();
|
||||
@Test boolean _methodOne() {
|
||||
|
||||
@Test
|
||||
boolean _methodOne() {
|
||||
return
|
||||
testObject.methodOne().equals("This is methodOne");
|
||||
}
|
||||
@Test boolean _methodTwo() {
|
||||
|
||||
@Test
|
||||
boolean _methodTwo() {
|
||||
return testObject.methodTwo() == 2;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OSExecute.command(
|
||||
"java net.mindview.atunit.AtUnit AtUnitComposition");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//: annotations/AtUnitExample1.java
|
||||
package annotations;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
@@ -7,18 +8,38 @@ public class AtUnitExample1 {
|
||||
public String methodOne() {
|
||||
return "This is methodOne";
|
||||
}
|
||||
|
||||
public int methodTwo() {
|
||||
System.out.println("This is methodTwo");
|
||||
return 2;
|
||||
}
|
||||
@Test boolean methodOneTest() {
|
||||
|
||||
@Test
|
||||
boolean methodOneTest() {
|
||||
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:
|
||||
@Test boolean failureTest() { return false; }
|
||||
@Test boolean anotherDisappointment() { return false; }
|
||||
@Test
|
||||
boolean failureTest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
boolean anotherDisappointment() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OSExecute.command(
|
||||
"java net.mindview.atunit.AtUnit AtUnitExample1");
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
//: annotations/AtUnitExample2.java
|
||||
// Assertions and exceptions can be used in @Tests.
|
||||
package annotations;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
@@ -9,24 +11,34 @@ public class AtUnitExample2 {
|
||||
public String methodOne() {
|
||||
return "This is methodOne";
|
||||
}
|
||||
|
||||
public int methodTwo() {
|
||||
System.out.println("This is methodTwo");
|
||||
return 2;
|
||||
}
|
||||
@Test void assertExample() {
|
||||
|
||||
@Test
|
||||
void assertExample() {
|
||||
assert methodOne().equals("This is methodOne");
|
||||
}
|
||||
@Test void assertFailureExample() {
|
||||
|
||||
@Test
|
||||
void assertFailureExample() {
|
||||
assert 1 == 2 : "What a surprise!";
|
||||
}
|
||||
@Test void exceptionExample() throws IOException {
|
||||
|
||||
@Test
|
||||
void exceptionExample() throws IOException {
|
||||
new FileInputStream("nofile.txt"); // Throws
|
||||
}
|
||||
@Test boolean assertAndReturn() {
|
||||
|
||||
@Test
|
||||
boolean assertAndReturn() {
|
||||
// Assertion with message:
|
||||
assert methodTwo() == 2 : "methodTwo must equal 2";
|
||||
return methodOne().equals("This is methodOne");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OSExecute.command(
|
||||
"java net.mindview.atunit.AtUnit AtUnitExample2");
|
||||
|
||||
@@ -1,27 +1,49 @@
|
||||
//: annotations/AtUnitExample3.java
|
||||
package annotations;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class AtUnitExample3 {
|
||||
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() {
|
||||
return "This is methodOne";
|
||||
}
|
||||
|
||||
public int methodTwo() {
|
||||
System.out.println("This is methodTwo");
|
||||
return 2;
|
||||
}
|
||||
@TestObjectCreate static AtUnitExample3 create() {
|
||||
|
||||
@TestObjectCreate
|
||||
static AtUnitExample3 create() {
|
||||
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");
|
||||
}
|
||||
@Test boolean m2() { return methodTwo() == 2; }
|
||||
|
||||
@Test
|
||||
boolean m2() {
|
||||
return methodTwo() == 2;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OSExecute.command(
|
||||
"java net.mindview.atunit.AtUnit AtUnitExample3");
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
//: annotations/AtUnitExample4.java
|
||||
package annotations;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class AtUnitExample4 {
|
||||
@@ -11,8 +14,15 @@ public class AtUnitExample4 {
|
||||
"middle, and then thin again at the far end.";
|
||||
private String word;
|
||||
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() {
|
||||
List<Character> chars = new ArrayList<Character>();
|
||||
for (Character c : word.toCharArray()) {
|
||||
@@ -25,22 +35,30 @@ public class AtUnitExample4 {
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
@TestProperty static List<String> input =
|
||||
|
||||
@TestProperty
|
||||
static List<String> input =
|
||||
Arrays.asList(theory.split(" "));
|
||||
@TestProperty
|
||||
static Iterator<String> words = input.iterator();
|
||||
@TestObjectCreate static AtUnitExample4 create() {
|
||||
|
||||
@TestObjectCreate
|
||||
static AtUnitExample4 create() {
|
||||
if (words.hasNext()) {
|
||||
return new AtUnitExample4(words.next());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Test boolean words() {
|
||||
|
||||
@Test
|
||||
boolean words() {
|
||||
print("'" + getWord() + "'");
|
||||
return getWord().equals("are");
|
||||
}
|
||||
@Test boolean scramble1() {
|
||||
|
||||
@Test
|
||||
boolean scramble1() {
|
||||
// Change to a specific seed to get verifiable results:
|
||||
rand = new Random(47);
|
||||
print("'" + getWord() + "'");
|
||||
@@ -48,13 +66,16 @@ public class AtUnitExample4 {
|
||||
print(scrambled);
|
||||
return scrambled.equals("lAl");
|
||||
}
|
||||
@Test boolean scramble2() {
|
||||
|
||||
@Test
|
||||
boolean scramble2() {
|
||||
rand = new Random(74);
|
||||
print("'" + getWord() + "'");
|
||||
String scrambled = scrambleWord();
|
||||
print(scrambled);
|
||||
return scrambled.equals("tsaeborornussu");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("starting");
|
||||
OSExecute.command(
|
||||
|
||||
@@ -1,16 +1,30 @@
|
||||
//: annotations/AtUnitExample5.java
|
||||
package annotations;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class AtUnitExample5 {
|
||||
private String text;
|
||||
public AtUnitExample5(String text) { this.text = text; }
|
||||
public String toString() { return text; }
|
||||
@TestProperty static PrintWriter output;
|
||||
@TestProperty static int counter;
|
||||
@TestObjectCreate static AtUnitExample5 create() {
|
||||
|
||||
public AtUnitExample5(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@TestProperty
|
||||
static PrintWriter output;
|
||||
@TestProperty
|
||||
static int counter;
|
||||
|
||||
@TestObjectCreate
|
||||
static AtUnitExample5 create() {
|
||||
String id = Integer.toString(counter++);
|
||||
try {
|
||||
output = new PrintWriter("Test" + id + ".txt");
|
||||
@@ -19,23 +33,32 @@ public class AtUnitExample5 {
|
||||
}
|
||||
return new AtUnitExample5(id);
|
||||
}
|
||||
@TestObjectCleanup static void
|
||||
|
||||
@TestObjectCleanup
|
||||
static void
|
||||
cleanup(AtUnitExample5 tobj) {
|
||||
System.out.println("Running cleanup");
|
||||
output.close();
|
||||
}
|
||||
@Test boolean test1() {
|
||||
|
||||
@Test
|
||||
boolean test1() {
|
||||
output.print("test1");
|
||||
return true;
|
||||
}
|
||||
@Test boolean test2() {
|
||||
|
||||
@Test
|
||||
boolean test2() {
|
||||
output.print("test2");
|
||||
return true;
|
||||
}
|
||||
@Test boolean test3() {
|
||||
|
||||
@Test
|
||||
boolean test3() {
|
||||
output.print("test3");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OSExecute.command(
|
||||
"java net.mindview.atunit.AtUnit AtUnitExample5");
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
//: annotations/AtUnitExternalTest.java
|
||||
// Creating non-embedded tests.
|
||||
package annotations;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class AtUnitExternalTest extends AtUnitExample1 {
|
||||
@Test boolean _methodOne() {
|
||||
@Test
|
||||
boolean _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 {
|
||||
OSExecute.command(
|
||||
"java net.mindview.atunit.AtUnit AtUnitExternalTest");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//: annotations/ExtractInterface.java
|
||||
// APT-based annotation processing.
|
||||
package annotations;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
|
||||
@@ -1,23 +1,32 @@
|
||||
//: annotations/HashSetTest.java
|
||||
package annotations;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class HashSetTest {
|
||||
HashSet<String> testObject = new HashSet<String>();
|
||||
@Test void initialization() {
|
||||
|
||||
@Test
|
||||
void initialization() {
|
||||
assert testObject.isEmpty();
|
||||
}
|
||||
@Test void _contains() {
|
||||
|
||||
@Test
|
||||
void _contains() {
|
||||
testObject.add("one");
|
||||
assert testObject.contains("one");
|
||||
}
|
||||
@Test void _remove() {
|
||||
|
||||
@Test
|
||||
void _remove() {
|
||||
testObject.add("one");
|
||||
testObject.remove("one");
|
||||
assert testObject.isEmpty();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OSExecute.command(
|
||||
"java net.mindview.atunit.AtUnit HashSetTest");
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
// annotations.InterfaceExtractorProcessorFactory
|
||||
// Multiplier.java -s ../annotations}
|
||||
package annotations;
|
||||
|
||||
import com.sun.mirror.apt.*;
|
||||
import com.sun.mirror.declaration.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
@@ -14,8 +16,12 @@ public class InterfaceExtractorProcessor
|
||||
private final AnnotationProcessorEnvironment env;
|
||||
private ArrayList<MethodDeclaration> interfaceMethods =
|
||||
new ArrayList<MethodDeclaration>();
|
||||
|
||||
public InterfaceExtractorProcessor(
|
||||
AnnotationProcessorEnvironment env) { this.env = env; }
|
||||
AnnotationProcessorEnvironment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public void process() {
|
||||
for (TypeDeclaration typeDecl :
|
||||
env.getSpecifiedTypeDeclarations()) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
//: annotations/InterfaceExtractorProcessorFactory.java
|
||||
// APT-based annotation processing.
|
||||
package annotations;
|
||||
|
||||
import com.sun.mirror.apt.*;
|
||||
import com.sun.mirror.declaration.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class InterfaceExtractorProcessorFactory
|
||||
@@ -12,10 +14,12 @@ public class InterfaceExtractorProcessorFactory
|
||||
AnnotationProcessorEnvironment env) {
|
||||
return new InterfaceExtractorProcessor(env);
|
||||
}
|
||||
|
||||
public Collection<String> supportedAnnotationTypes() {
|
||||
return
|
||||
Collections.singleton("annotations.ExtractInterface");
|
||||
}
|
||||
|
||||
public Collection<String> supportedOptions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,11 @@ public class Multiplier {
|
||||
}
|
||||
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) {
|
||||
Multiplier m = new Multiplier();
|
||||
System.out.println("11*16 = " + m.multiply(11, 16));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package annotations;//: annotations/PasswordUtils.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PasswordUtils {
|
||||
@@ -7,10 +8,12 @@ public class PasswordUtils {
|
||||
public boolean validatePassword(String password) {
|
||||
return (password.matches("\\w*\\d\\w*"));
|
||||
}
|
||||
|
||||
@UseCase(id = 48)
|
||||
public String encryptPassword(String password) {
|
||||
return new StringBuilder(password).reverse().toString();
|
||||
}
|
||||
|
||||
@UseCase(id = 49, description =
|
||||
"New passwords can't equal previously used ones")
|
||||
public boolean checkForNewPassword(
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package annotations;//: annotations/SimulatingNull.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SimulatingNull {
|
||||
public int id() default -1;
|
||||
|
||||
public String description() default "";
|
||||
} ///:~
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
//: annotations/StackL.java
|
||||
// A stack built on a linkedList.
|
||||
package annotations;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class StackL<T> {
|
||||
private LinkedList<T> list = new LinkedList<T>();
|
||||
public void push(T v) { list.addFirst(v); }
|
||||
public T top() { return list.getFirst(); }
|
||||
public T pop() { return list.removeFirst(); }
|
||||
|
||||
public void push(T v) {
|
||||
list.addFirst(v);
|
||||
}
|
||||
|
||||
public T top() {
|
||||
return list.getFirst();
|
||||
}
|
||||
|
||||
public T pop() {
|
||||
return list.removeFirst();
|
||||
}
|
||||
} ///:~
|
||||
|
||||
@@ -1,28 +1,35 @@
|
||||
//: annotations/StackLStringTest.java
|
||||
// Applying @Unit to generics.
|
||||
package annotations;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class StackLStringTest extends StackL<String> {
|
||||
@Test void _push() {
|
||||
@Test
|
||||
void _push() {
|
||||
push("one");
|
||||
assert top().equals("one");
|
||||
push("two");
|
||||
assert top().equals("two");
|
||||
}
|
||||
@Test void _pop() {
|
||||
|
||||
@Test
|
||||
void _pop() {
|
||||
push("one");
|
||||
push("two");
|
||||
assert pop().equals("two");
|
||||
assert pop().equals("one");
|
||||
}
|
||||
@Test void _top() {
|
||||
|
||||
@Test
|
||||
void _top() {
|
||||
push("A");
|
||||
push("B");
|
||||
assert top().equals("B");
|
||||
assert top().equals("B");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OSExecute.command(
|
||||
"java net.mindview.atunit.AtUnit StackLStringTest");
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
//: annotations/Testable.java
|
||||
package annotations;
|
||||
|
||||
import net.mindview.atunit.*;
|
||||
|
||||
public class Testable {
|
||||
public void execute() {
|
||||
System.out.println("Executing..");
|
||||
}
|
||||
@Test void testExecute() { execute(); }
|
||||
|
||||
@Test
|
||||
void testExecute() {
|
||||
execute();
|
||||
}
|
||||
} ///:~
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package annotations;//: annotations/UseCase.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface UseCase {
|
||||
public int id();
|
||||
|
||||
public String description() default "no description";
|
||||
} ///:~
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package annotations;//: annotations/UseCaseTracker.java
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
@@ -17,6 +18,7 @@ public class UseCaseTracker {
|
||||
System.out.println("Warning: Missing use case-" + i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<Integer> useCases = new ArrayList<Integer>();
|
||||
Collections.addAll(useCases, 47, 48, 49, 50);
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
//: annotations/database/Constraints.java
|
||||
package annotations.database;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Constraints {
|
||||
boolean primaryKey() default false;
|
||||
|
||||
boolean allowNull() default true;
|
||||
|
||||
boolean unique() default false;
|
||||
} ///:~
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//: annotations/database/DBTable.java
|
||||
package annotations.database;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.TYPE) // Applies to classes only
|
||||
|
||||
@@ -3,16 +3,35 @@ package annotations.database;
|
||||
|
||||
@DBTable(name = "MEMBER")
|
||||
public class Member {
|
||||
@SQLString(30) String firstName;
|
||||
@SQLString(50) String lastName;
|
||||
@SQLInteger Integer age;
|
||||
@SQLString(30)
|
||||
String firstName;
|
||||
@SQLString(50)
|
||||
String lastName;
|
||||
@SQLInteger
|
||||
Integer age;
|
||||
@SQLString(value = 30,
|
||||
constraints = @Constraints(primaryKey = true))
|
||||
String handle;
|
||||
static int memberCount;
|
||||
public String getHandle() { return handle; }
|
||||
public String getFirstName() { return firstName; }
|
||||
public String getLastName() { return lastName; }
|
||||
public String toString() { return handle; }
|
||||
public Integer getAge() { return age; }
|
||||
|
||||
public String getHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
} ///:~
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
//: annotations/database/SQLInteger.java
|
||||
package annotations.database;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SQLInteger {
|
||||
String name() default "";
|
||||
|
||||
Constraints constraints() default @Constraints;
|
||||
} ///:~
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
//: annotations/database/SQLString.java
|
||||
package annotations.database;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SQLString {
|
||||
int value() default 0;
|
||||
|
||||
String name() default "";
|
||||
|
||||
Constraints constraints() default @Constraints;
|
||||
} ///:~
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
// annotations.database.TableCreationProcessorFactory
|
||||
// database/Member.java -s database}
|
||||
package annotations.database;
|
||||
|
||||
import com.sun.mirror.apt.*;
|
||||
import com.sun.mirror.declaration.*;
|
||||
import com.sun.mirror.util.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.sun.mirror.util.DeclarationVisitors.*;
|
||||
|
||||
public class TableCreationProcessorFactory
|
||||
@@ -17,6 +20,7 @@ public class TableCreationProcessorFactory
|
||||
AnnotationProcessorEnvironment env) {
|
||||
return new TableCreationProcessor(env);
|
||||
}
|
||||
|
||||
public Collection<String> supportedAnnotationTypes() {
|
||||
return Arrays.asList(
|
||||
"annotations.database.DBTable",
|
||||
@@ -24,17 +28,21 @@ public class TableCreationProcessorFactory
|
||||
"annotations.database.SQLString",
|
||||
"annotations.database.SQLInteger");
|
||||
}
|
||||
|
||||
public Collection<String> supportedOptions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
private static class TableCreationProcessor
|
||||
implements AnnotationProcessor {
|
||||
private final AnnotationProcessorEnvironment env;
|
||||
private String sql = "";
|
||||
|
||||
public TableCreationProcessor(
|
||||
AnnotationProcessorEnvironment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public void process() {
|
||||
for (TypeDeclaration typeDecl :
|
||||
env.getSpecifiedTypeDeclarations()) {
|
||||
@@ -45,6 +53,7 @@ public class TableCreationProcessorFactory
|
||||
sql = "";
|
||||
}
|
||||
}
|
||||
|
||||
private class TableCreationVisitor
|
||||
extends SimpleDeclarationVisitor {
|
||||
public void visitClassDeclaration(
|
||||
@@ -58,6 +67,7 @@ public class TableCreationProcessorFactory
|
||||
sql += " (";
|
||||
}
|
||||
}
|
||||
|
||||
public void visitFieldDeclaration(
|
||||
FieldDeclaration d) {
|
||||
String columnName = "";
|
||||
@@ -87,6 +97,7 @@ public class TableCreationProcessorFactory
|
||||
getConstraints(sString.constraints()) + ",";
|
||||
}
|
||||
}
|
||||
|
||||
private String getConstraints(Constraints con) {
|
||||
String constraints = "";
|
||||
if (!con.allowNull()) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Reflection-based annotation processor.
|
||||
// {Args: annotations.database.Member}
|
||||
package annotations.database;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
@@ -68,6 +69,7 @@ public class TableCreator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getConstraints(Constraints con) {
|
||||
String constraints = "";
|
||||
if (!con.allowNull()) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package arrays;//: arrays/AlphabeticSearch.java
|
||||
// Searching with a Comparator.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class AlphabeticSearch {
|
||||
|
||||
@@ -3,6 +3,7 @@ package arrays;//: arrays/ArrayOfGenericType.java
|
||||
|
||||
public class ArrayOfGenericType<T> {
|
||||
T[] array; // OK
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ArrayOfGenericType(int size) {
|
||||
//! array = new T[size]; // Illegal
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package arrays;//: arrays/ArrayOfGenerics.java
|
||||
// It is possible to create arrays of generics.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ArrayOfGenerics {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package arrays;//: arrays/ArrayOptions.java
|
||||
// Initialization & re-assignment of arrays.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class ArrayOptions {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package arrays;//: arrays/ArraySearching.java
|
||||
// Using Arrays.binarySearch().
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class ArraySearching {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package arrays;//: arrays/AssemblingMultidimensionalArrays.java
|
||||
// Creating multidimensional arrays.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AssemblingMultidimensionalArrays {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package arrays;//: arrays/AutoboxingArrays.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AutoboxingArrays {
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
package arrays;//: arrays/CompType.java
|
||||
// Implementing Comparable in a class.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class CompType implements Comparable<CompType> {
|
||||
int i;
|
||||
int j;
|
||||
private static int count = 1;
|
||||
|
||||
public CompType(int n1, int n2) {
|
||||
i = n1;
|
||||
j = n2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String result = "[i = " + i + ", j = " + j + "]";
|
||||
if (count++ % 3 == 0) {
|
||||
@@ -19,17 +25,23 @@ public class CompType implements Comparable<CompType> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(CompType rv) {
|
||||
return (i < rv.i ? -1 : (i == rv.i ? 0 : 1));
|
||||
}
|
||||
|
||||
private static Random r = new Random(47);
|
||||
|
||||
public static Generator<CompType> generator() {
|
||||
return new Generator<CompType>() {
|
||||
@Override
|
||||
public CompType next() {
|
||||
return new CompType(r.nextInt(100), r.nextInt(100));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
CompType[] a =
|
||||
Generated.array(new CompType[12], generator());
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package arrays;//: arrays/ComparatorTest.java
|
||||
// Implementing a Comparator for a class.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
class CompTypeComparator implements Comparator<CompType> {
|
||||
@Override
|
||||
public int compare(CompType o1, CompType o2) {
|
||||
return (o1.j < o2.j ? -1 : (o1.j == o2.j ? 0 : 1));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package arrays;//: arrays/ComparingArrays.java
|
||||
// Using Arrays.equals()
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class ComparingArrays {
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
package arrays;//: arrays/ContainerComparison.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
class BerylliumSphere {
|
||||
private static long counter;
|
||||
private final long id = counter++;
|
||||
public String toString() { return "Sphere " + id; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Sphere " + id;
|
||||
}
|
||||
}
|
||||
|
||||
public class ContainerComparison {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package arrays;//: arrays/CopyingArrays.java
|
||||
// Using System.arraycopy()
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class CopyingArrays {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package arrays;//: arrays/FillingArrays.java
|
||||
// Using Arrays.fill()
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class FillingArrays {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package arrays;//: arrays/GeneratorsTest.java
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class GeneratorsTest {
|
||||
public static int size = 10;
|
||||
|
||||
public static void test(Class<?> surroundingClass) {
|
||||
for (Class<?> type : surroundingClass.getClasses()) {
|
||||
System.out.print(type.getSimpleName() + ": ");
|
||||
@@ -17,6 +19,7 @@ public class GeneratorsTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(CountingGenerator.class);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package arrays;//: arrays/IceCream.java
|
||||
// Returning arrays from methods.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class IceCream {
|
||||
@@ -9,6 +10,7 @@ public class IceCream {
|
||||
"Mint Chip", "Mocha Almond Fudge", "Rum Raisin",
|
||||
"Praline Cream", "Mud Pie"
|
||||
};
|
||||
|
||||
public static String[] flavorSet(int n) {
|
||||
if (n > FLAVORS.length) {
|
||||
throw new IllegalArgumentException("Set too big");
|
||||
@@ -26,6 +28,7 @@ public class IceCream {
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
System.out.println(Arrays.toString(flavorSet(3)));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package arrays;//: arrays/MultiDimWrapperArray.java
|
||||
// Multidimensional arrays of "wrapper" objects.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MultiDimWrapperArray {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package arrays;//: arrays/MultidimensionalObjectArrays.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MultidimensionalObjectArrays {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package arrays;//: arrays/MultidimensionalPrimitiveArray.java
|
||||
// Creating multidimensional arrays.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MultidimensionalPrimitiveArray {
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package arrays;//: arrays/ParameterizedArrayType.java
|
||||
|
||||
class ClassParameter<T> {
|
||||
public T[] f(T[] arg) { return arg; }
|
||||
public T[] f(T[] arg) {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
||||
class MethodParameter {
|
||||
public static <T> T[] f(T[] arg) { return arg; }
|
||||
public static <T> T[] f(T[] arg) {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
||||
public class ParameterizedArrayType {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package arrays;//: arrays/PrimitiveConversionDemonstration.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class PrimitiveConversionDemonstration {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package arrays;//: arrays/RaggedArray.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class RaggedArray {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package arrays;//: arrays/RandomGeneratorsTest.java
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class RandomGeneratorsTest {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package arrays;//: arrays/Reverse.java
|
||||
// The Collections.reverseOrder() Comparator
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class Reverse {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package arrays;//: arrays/StringSorting.java
|
||||
// Sorting an array of Strings.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class StringSorting {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package arrays;//: arrays/TestArrayGeneration.java
|
||||
// Test the tools that use generators to fill arrays.
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class TestArrayGeneration {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package arrays;//: arrays/TestGenerated.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
public class TestGenerated {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package arrays;//: arrays/ThreeDWithNew.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ThreeDWithNew {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//: bangbean/BangBean.java
|
||||
// A graphical Bean.
|
||||
package bangbean;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
@@ -15,31 +16,51 @@ BangBean extends JPanel implements Serializable {
|
||||
private int fontSize = 48;
|
||||
private Color tColor = Color.RED;
|
||||
private ActionListener actionListener;
|
||||
|
||||
public BangBean() {
|
||||
addMouseListener(new ML());
|
||||
addMouseMotionListener(new MML());
|
||||
}
|
||||
public int getCircleSize() { return cSize; }
|
||||
|
||||
public int getCircleSize() {
|
||||
return cSize;
|
||||
}
|
||||
|
||||
public void setCircleSize(int newSize) {
|
||||
cSize = newSize;
|
||||
}
|
||||
public String getBangText() { return text; }
|
||||
|
||||
public String getBangText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setBangText(String newText) {
|
||||
text = newText;
|
||||
}
|
||||
public int getFontSize() { return fontSize; }
|
||||
|
||||
public int getFontSize() {
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
public void setFontSize(int newSize) {
|
||||
fontSize = newSize;
|
||||
}
|
||||
public Color getTextColor() { return tColor; }
|
||||
|
||||
public Color getTextColor() {
|
||||
return tColor;
|
||||
}
|
||||
|
||||
public void setTextColor(Color newColor) {
|
||||
tColor = newColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
g.setColor(Color.BLACK);
|
||||
g.drawOval(xm - cSize / 2, ym - cSize / 2, cSize, cSize);
|
||||
}
|
||||
|
||||
// This is a unicast listener, which is
|
||||
// the simplest form of listener management:
|
||||
public void addActionListener(ActionListener l)
|
||||
@@ -49,10 +70,13 @@ BangBean extends JPanel implements Serializable {
|
||||
}
|
||||
actionListener = l;
|
||||
}
|
||||
|
||||
public void removeActionListener(ActionListener l) {
|
||||
actionListener = null;
|
||||
}
|
||||
|
||||
class ML extends MouseAdapter {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
Graphics g = getGraphics();
|
||||
g.setColor(tColor);
|
||||
@@ -70,13 +94,17 @@ BangBean extends JPanel implements Serializable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MML extends MouseMotionAdapter {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
xm = e.getX();
|
||||
ym = e.getY();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(200, 200);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
//: bangbean/BangBeanTest.java
|
||||
// {Timeout: 5} Abort after 5 seconds when testing
|
||||
package bangbean;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.SwingConsole.*;
|
||||
|
||||
public class BangBeanTest extends JFrame {
|
||||
private JTextField txt = new JTextField(20);
|
||||
|
||||
// During testing, report actions:
|
||||
class BBL implements ActionListener {
|
||||
private int count = 0;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
txt.setText("BangBean action " + count++);
|
||||
}
|
||||
}
|
||||
|
||||
public BangBeanTest() {
|
||||
BangBean bb = new BangBean();
|
||||
try {
|
||||
@@ -26,6 +32,7 @@ public class BangBeanTest extends JFrame {
|
||||
add(bb);
|
||||
add(BorderLayout.SOUTH, txt);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
run(new BangBeanTest(), 400, 500);
|
||||
}
|
||||
|
||||
@@ -2,14 +2,17 @@ package concurrency;//: concurrency/ActiveObjectDemo.java
|
||||
// Can only pass constants, immutables, "disconnected
|
||||
// objects," or other active objects as arguments
|
||||
// to asynch methods.
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class ActiveObjectDemo {
|
||||
private ExecutorService ex =
|
||||
Executors.newSingleThreadExecutor();
|
||||
private Random rand = new Random(47);
|
||||
|
||||
// Insert a random delay to produce the effect
|
||||
// of a calculation time:
|
||||
private void pause(int factor) {
|
||||
@@ -20,9 +23,11 @@ public class ActiveObjectDemo {
|
||||
print("sleep() interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
public Future<Integer>
|
||||
calculateInt(final int x, final int y) {
|
||||
return ex.submit(new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() {
|
||||
print("starting " + x + " + " + y);
|
||||
pause(500);
|
||||
@@ -30,9 +35,11 @@ public class ActiveObjectDemo {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Future<Float>
|
||||
calculateFloat(final float x, final float y) {
|
||||
return ex.submit(new Callable<Float>() {
|
||||
@Override
|
||||
public Float call() {
|
||||
print("starting " + x + " + " + y);
|
||||
pause(2000);
|
||||
@@ -40,7 +47,11 @@ public class ActiveObjectDemo {
|
||||
}
|
||||
});
|
||||
}
|
||||
public void shutdown() { ex.shutdown(); }
|
||||
|
||||
public void shutdown() {
|
||||
ex.shutdown();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ActiveObjectDemo d1 = new ActiveObjectDemo();
|
||||
// Prevents ConcurrentModificationException:
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package concurrency;//: concurrency/AtomicEvenGenerator.java
|
||||
// Atomic classes are occasionally useful in regular code.
|
||||
// {RunByHand}
|
||||
|
||||
import java.util.concurrent.atomic.*;
|
||||
|
||||
public class AtomicEvenGenerator extends IntGenerator {
|
||||
private AtomicInteger currentEvenValue =
|
||||
new AtomicInteger(0);
|
||||
|
||||
@Override
|
||||
public int next() {
|
||||
return currentEvenValue.addAndGet(2);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
EvenChecker.test(new AtomicEvenGenerator());
|
||||
}
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
package concurrency;//: concurrency/AtomicIntegerTest.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.*;
|
||||
|
||||
public class AtomicIntegerTest implements Runnable {
|
||||
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() {
|
||||
while (true) {
|
||||
evenIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Timer().schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.err.println("Aborting");
|
||||
System.exit(0);
|
||||
|
||||
@@ -3,8 +3,14 @@ package concurrency;//: concurrency/Atomicity.java
|
||||
|
||||
public class Atomicity {
|
||||
int i;
|
||||
void f1() { i++; }
|
||||
void f2() { i += 3; }
|
||||
|
||||
void f1() {
|
||||
i++;
|
||||
}
|
||||
|
||||
void f2() {
|
||||
i += 3;
|
||||
}
|
||||
} /* Output: (Sample)
|
||||
...
|
||||
void f1();
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
package concurrency;//: concurrency/AtomicityTest.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class AtomicityTest implements Runnable {
|
||||
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() {
|
||||
while (true) {
|
||||
evenIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ExecutorService exec = Executors.newCachedThreadPool();
|
||||
AtomicityTest at = new AtomicityTest();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package concurrency;//: concurrency/AttemptLocking.java
|
||||
// Locks in the concurrent library allow you
|
||||
// to give up on trying to acquire a lock.
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.locks.*;
|
||||
|
||||
public class AttemptLocking {
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public void untimed() {
|
||||
boolean captured = lock.tryLock();
|
||||
try {
|
||||
@@ -16,6 +18,7 @@ public class AttemptLocking {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void timed() {
|
||||
boolean captured = false;
|
||||
try {
|
||||
@@ -32,13 +35,18 @@ public class AttemptLocking {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
final AttemptLocking al = new AttemptLocking();
|
||||
al.untimed(); // True -- lock is available
|
||||
al.timed(); // True -- lock is available
|
||||
// Now create a separate task to grab the lock:
|
||||
new Thread() {
|
||||
{ setDaemon(true); }
|
||||
{
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
al.lock.lock();
|
||||
System.out.println("acquired");
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
package concurrency;//: concurrency/BankTellerSimulation.java
|
||||
// Using queues and multithreading.
|
||||
// {Args: 5}
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
// Read-only objects don't require synchronization:
|
||||
class Customer {
|
||||
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() {
|
||||
return "[" + serviceTime + "]";
|
||||
}
|
||||
@@ -19,6 +28,8 @@ class CustomerLine extends ArrayBlockingQueue<Customer> {
|
||||
public CustomerLine(int maxLineSize) {
|
||||
super(maxLineSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this.size() == 0) {
|
||||
return "[Empty]";
|
||||
@@ -35,9 +46,12 @@ class CustomerLine extends ArrayBlockingQueue<Customer> {
|
||||
class CustomerGenerator implements Runnable {
|
||||
private CustomerLine customers;
|
||||
private static Random rand = new Random(47);
|
||||
|
||||
public CustomerGenerator(CustomerLine cq) {
|
||||
customers = cq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -58,7 +72,12 @@ class Teller implements Runnable, Comparable<Teller> {
|
||||
private int customersServed = 0;
|
||||
private CustomerLine customers;
|
||||
private boolean servingCustomerLine = true;
|
||||
public Teller(CustomerLine cq) { customers = cq; }
|
||||
|
||||
public Teller(CustomerLine cq) {
|
||||
customers = cq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -77,18 +96,29 @@ class Teller implements Runnable, Comparable<Teller> {
|
||||
}
|
||||
System.out.println(this + "terminating");
|
||||
}
|
||||
|
||||
public synchronized void doSomethingElse() {
|
||||
customersServed = 0;
|
||||
servingCustomerLine = false;
|
||||
}
|
||||
|
||||
public synchronized void serveCustomerLine() {
|
||||
assert !servingCustomerLine : "already serving: " + this;
|
||||
servingCustomerLine = true;
|
||||
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:
|
||||
@Override
|
||||
public synchronized int compareTo(Teller other) {
|
||||
return customersServed < other.customersServed ? -1 :
|
||||
(customersServed == other.customersServed ? 0 : 1);
|
||||
@@ -104,6 +134,7 @@ class TellerManager implements Runnable {
|
||||
new LinkedList<Teller>();
|
||||
private int adjustmentPeriod;
|
||||
private static Random rand = new Random(47);
|
||||
|
||||
public TellerManager(ExecutorService e,
|
||||
CustomerLine customers, int adjustmentPeriod) {
|
||||
exec = e;
|
||||
@@ -114,6 +145,7 @@ class TellerManager implements Runnable {
|
||||
exec.execute(teller);
|
||||
workingTellers.add(teller);
|
||||
}
|
||||
|
||||
public void adjustTellerNumber() {
|
||||
// This is actually a control system. By adjusting
|
||||
// the numbers, you can reveal stability issues in
|
||||
@@ -146,12 +178,15 @@ class TellerManager implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Give a teller a different job or a break:
|
||||
private void reassignOneTeller() {
|
||||
Teller teller = workingTellers.poll();
|
||||
teller.doSomethingElse();
|
||||
tellersDoingOtherThings.offer(teller);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -168,12 +203,17 @@ class TellerManager implements Runnable {
|
||||
}
|
||||
System.out.println(this + "terminating");
|
||||
}
|
||||
public String toString() { return "TellerManager "; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TellerManager ";
|
||||
}
|
||||
}
|
||||
|
||||
public class BankTellerSimulation {
|
||||
static final int MAX_LINE_SIZE = 50;
|
||||
static final int ADJUSTMENT_PERIOD = 1000;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ExecutorService exec = Executors.newCachedThreadPool();
|
||||
// If line is too long, customers will leave:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package concurrency;//: concurrency/CachedThreadPool.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class CachedThreadPool {
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package concurrency;//: concurrency/CallableDemo.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
class TaskWithResult implements Callable<String> {
|
||||
private int id;
|
||||
|
||||
public TaskWithResult(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String call() {
|
||||
return "result of TaskWithResult " + id;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package concurrency;//: concurrency/CaptureUncaughtException.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
class ExceptionThread2 implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
Thread t = Thread.currentThread();
|
||||
System.out.println("run() by " + t);
|
||||
@@ -13,12 +15,14 @@ class ExceptionThread2 implements Runnable {
|
||||
|
||||
class MyUncaughtExceptionHandler implements
|
||||
Thread.UncaughtExceptionHandler {
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
System.out.println("caught " + e);
|
||||
}
|
||||
}
|
||||
|
||||
class HandlerThreadFactory implements ThreadFactory {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
System.out.println(this + " creating new Thread");
|
||||
Thread t = new Thread(r);
|
||||
|
||||
@@ -1,22 +1,42 @@
|
||||
package concurrency;//: concurrency/CarBuilder.java
|
||||
// A complex example of tasks working together.
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
class Car {
|
||||
private final int id;
|
||||
private boolean
|
||||
engine = false, driveTrain = false, wheels = false;
|
||||
public Car(int idn) { id = idn; }
|
||||
|
||||
public Car(int idn) {
|
||||
id = idn;
|
||||
}
|
||||
|
||||
// Empty Car object:
|
||||
public Car() { id = -1; }
|
||||
public synchronized int getId() { return id; }
|
||||
public synchronized void addEngine() { engine = true; }
|
||||
public Car() {
|
||||
id = -1;
|
||||
}
|
||||
|
||||
public synchronized int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public synchronized void addEngine() {
|
||||
engine = true;
|
||||
}
|
||||
|
||||
public synchronized void addDriveTrain() {
|
||||
driveTrain = true;
|
||||
}
|
||||
public synchronized void addWheels() { wheels = true; }
|
||||
|
||||
public synchronized void addWheels() {
|
||||
wheels = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String toString() {
|
||||
return "Car " + id + " [" + " engine: " + engine
|
||||
+ " driveTrain: " + driveTrain
|
||||
@@ -24,12 +44,18 @@ class Car {
|
||||
}
|
||||
}
|
||||
|
||||
class CarQueue extends LinkedBlockingQueue<Car> {}
|
||||
class CarQueue extends LinkedBlockingQueue<Car> {
|
||||
}
|
||||
|
||||
class ChassisBuilder implements Runnable {
|
||||
private CarQueue carQueue;
|
||||
private int counter = 0;
|
||||
public ChassisBuilder(CarQueue cq) { carQueue = cq; }
|
||||
|
||||
public ChassisBuilder(CarQueue cq) {
|
||||
carQueue = cq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -52,13 +78,22 @@ class Assembler implements Runnable {
|
||||
private Car car;
|
||||
private CyclicBarrier barrier = new CyclicBarrier(4);
|
||||
private RobotPool robotPool;
|
||||
|
||||
public Assembler(CarQueue cq, CarQueue fq, RobotPool rp) {
|
||||
chassisQueue = cq;
|
||||
finishingQueue = fq;
|
||||
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() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -84,7 +119,12 @@ class Assembler implements Runnable {
|
||||
|
||||
class Reporter implements Runnable {
|
||||
private CarQueue carQueue;
|
||||
public Reporter(CarQueue cq) { carQueue = cq; }
|
||||
|
||||
public Reporter(CarQueue cq) {
|
||||
carQueue = cq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -99,19 +139,29 @@ class Reporter implements Runnable {
|
||||
|
||||
abstract class Robot implements Runnable {
|
||||
private RobotPool pool;
|
||||
public Robot(RobotPool p) { pool = p; }
|
||||
|
||||
public Robot(RobotPool p) {
|
||||
pool = p;
|
||||
}
|
||||
|
||||
protected Assembler assembler;
|
||||
|
||||
public Robot assignAssembler(Assembler assembler) {
|
||||
this.assembler = assembler;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean engage = false;
|
||||
|
||||
public synchronized void engage() {
|
||||
engage = true;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
// The part of run() that's different for each robot:
|
||||
abstract protected void performService();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
powerDown(); // Wait until needed
|
||||
@@ -129,6 +179,7 @@ abstract class Robot implements Runnable {
|
||||
}
|
||||
print(this + " off");
|
||||
}
|
||||
|
||||
private synchronized void
|
||||
powerDown() throws InterruptedException {
|
||||
engage = false;
|
||||
@@ -140,11 +191,19 @@ abstract class Robot implements Runnable {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
public String toString() { return getClass().getName(); }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
class EngineRobot extends Robot {
|
||||
public EngineRobot(RobotPool pool) { super(pool); }
|
||||
public EngineRobot(RobotPool pool) {
|
||||
super(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performService() {
|
||||
print(this + " installing engine");
|
||||
assembler.car().addEngine();
|
||||
@@ -152,7 +211,11 @@ class EngineRobot extends Robot {
|
||||
}
|
||||
|
||||
class DriveTrainRobot extends Robot {
|
||||
public DriveTrainRobot(RobotPool pool) { super(pool); }
|
||||
public DriveTrainRobot(RobotPool pool) {
|
||||
super(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performService() {
|
||||
print(this + " installing DriveTrain");
|
||||
assembler.car().addDriveTrain();
|
||||
@@ -160,7 +223,11 @@ class DriveTrainRobot extends Robot {
|
||||
}
|
||||
|
||||
class WheelRobot extends Robot {
|
||||
public WheelRobot(RobotPool pool) { super(pool); }
|
||||
public WheelRobot(RobotPool pool) {
|
||||
super(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performService() {
|
||||
print(this + " installing Wheels");
|
||||
assembler.car().addWheels();
|
||||
@@ -170,10 +237,12 @@ class WheelRobot extends Robot {
|
||||
class RobotPool {
|
||||
// Quietly prevents identical entries:
|
||||
private Set<Robot> pool = new HashSet<Robot>();
|
||||
|
||||
public synchronized void add(Robot r) {
|
||||
pool.add(r);
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized void
|
||||
hire(Class<? extends Robot> robotType, Assembler d)
|
||||
throws InterruptedException {
|
||||
@@ -188,7 +257,10 @@ class RobotPool {
|
||||
wait(); // None available
|
||||
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 {
|
||||
|
||||
@@ -3,13 +3,14 @@ package concurrency;//: concurrency/Chopstick.java
|
||||
|
||||
public class Chopstick {
|
||||
private boolean taken = false;
|
||||
public synchronized
|
||||
void take() throws InterruptedException {
|
||||
|
||||
public synchronized void take() throws InterruptedException {
|
||||
while (taken) {
|
||||
wait();
|
||||
}
|
||||
taken = true;
|
||||
}
|
||||
|
||||
public synchronized void drop() {
|
||||
taken = false;
|
||||
notifyAll();
|
||||
|
||||
@@ -2,9 +2,11 @@ package concurrency;//: concurrency/CloseResource.java
|
||||
// Interrupting a blocked task by
|
||||
// closing the underlying resource.
|
||||
// {RunByHand}
|
||||
|
||||
import java.net.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.io.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class CloseResource {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package concurrency;//: concurrency/CountDownLatchDemo.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
// Performs some portion of a task:
|
||||
@@ -9,9 +11,12 @@ class TaskPortion implements Runnable {
|
||||
private final int id = counter++;
|
||||
private static Random rand = new Random(47);
|
||||
private final CountDownLatch latch;
|
||||
|
||||
TaskPortion(CountDownLatch latch) {
|
||||
this.latch = latch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
doWork();
|
||||
@@ -20,10 +25,13 @@ class TaskPortion implements Runnable {
|
||||
// Acceptable way to exit
|
||||
}
|
||||
}
|
||||
|
||||
public void doWork() throws InterruptedException {
|
||||
TimeUnit.MILLISECONDS.sleep(rand.nextInt(2000));
|
||||
print(this + "completed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%1$-3d ", id);
|
||||
}
|
||||
@@ -34,9 +42,12 @@ class WaitingTask implements Runnable {
|
||||
private static int counter = 0;
|
||||
private final int id = counter++;
|
||||
private final CountDownLatch latch;
|
||||
|
||||
WaitingTask(CountDownLatch latch) {
|
||||
this.latch = latch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
latch.await();
|
||||
@@ -45,6 +56,8 @@ class WaitingTask implements Runnable {
|
||||
print(this + " interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("WaitingTask %1$-3d ", id);
|
||||
}
|
||||
@@ -52,6 +65,7 @@ class WaitingTask implements Runnable {
|
||||
|
||||
public class CountDownLatchDemo {
|
||||
static final int SIZE = 100;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ExecutorService exec = Executors.newCachedThreadPool();
|
||||
// All must share a single CountDownLatch object:
|
||||
|
||||
@@ -3,30 +3,51 @@
|
||||
// demonstrates protection of a non-thread-safe class
|
||||
// with a thread-safe one.
|
||||
package concurrency;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.*;
|
||||
|
||||
class Pair { // Not thread-safe
|
||||
private int x, y;
|
||||
|
||||
public Pair(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
public Pair() { this(0, 0); }
|
||||
public int getX() { return x; }
|
||||
public int getY() { return y; }
|
||||
public void incrementX() { x++; }
|
||||
public void incrementY() { y++; }
|
||||
|
||||
public Pair() {
|
||||
this(0, 0);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void incrementX() {
|
||||
x++;
|
||||
}
|
||||
|
||||
public void incrementY() {
|
||||
y++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "x: " + x + ", y: " + y;
|
||||
}
|
||||
|
||||
public class PairValuesNotEqualException
|
||||
extends RuntimeException {
|
||||
public PairValuesNotEqualException() {
|
||||
super("Pair values not equal: " + Pair.this);
|
||||
}
|
||||
}
|
||||
|
||||
// Arbitrary invariant -- both variables must be equal:
|
||||
public void checkState() {
|
||||
if (x != y) {
|
||||
@@ -41,22 +62,27 @@ abstract class PairManager {
|
||||
protected Pair p = new Pair();
|
||||
private List<Pair> storage =
|
||||
Collections.synchronizedList(new ArrayList<Pair>());
|
||||
|
||||
public synchronized Pair getPair() {
|
||||
// Make a copy to keep the original safe:
|
||||
return new Pair(p.getX(), p.getY());
|
||||
}
|
||||
|
||||
// Assume this is a time consuming operation
|
||||
protected void store(Pair p) {
|
||||
storage.add(p);
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
} catch(InterruptedException ignore) {}
|
||||
} catch (InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void increment();
|
||||
}
|
||||
|
||||
// Synchronize the entire method:
|
||||
class PairManager1 extends PairManager {
|
||||
@Override
|
||||
public synchronized void increment() {
|
||||
p.incrementX();
|
||||
p.incrementY();
|
||||
@@ -66,6 +92,7 @@ class PairManager1 extends PairManager {
|
||||
|
||||
// Use a critical section:
|
||||
class PairManager2 extends PairManager {
|
||||
@Override
|
||||
public void increment() {
|
||||
Pair temp;
|
||||
synchronized (this) {
|
||||
@@ -79,14 +106,19 @@ class PairManager2 extends PairManager {
|
||||
|
||||
class PairManipulator implements Runnable {
|
||||
private PairManager pm;
|
||||
|
||||
public PairManipulator(PairManager pm) {
|
||||
this.pm = pm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
pm.increment();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Pair: " + pm.getPair() +
|
||||
" checkCounter = " + pm.checkCounter.get();
|
||||
@@ -95,9 +127,12 @@ class PairManipulator implements Runnable {
|
||||
|
||||
class PairChecker implements Runnable {
|
||||
private PairManager pm;
|
||||
|
||||
public PairChecker(PairManager pm) {
|
||||
this.pm = pm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
pm.checkCounter.incrementAndGet();
|
||||
@@ -129,6 +164,7 @@ public class CriticalSection {
|
||||
System.out.println("pm1: " + pm1 + "\npm2: " + pm2);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PairManager
|
||||
pman1 = new PairManager1(),
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package concurrency;//: concurrency/DaemonFromFactory.java
|
||||
// Using a Thread Factory to create daemons.
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class DaemonFromFactory implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
@@ -15,6 +19,7 @@ public class DaemonFromFactory implements Runnable {
|
||||
print("Interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ExecutorService exec = Executors.newCachedThreadPool(
|
||||
new DaemonThreadFactory());
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package concurrency;//: concurrency/Daemons.java
|
||||
// Daemon threads spawn other daemon threads.
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
class Daemon implements Runnable {
|
||||
private Thread[] t = new Thread[10];
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < t.length; i++) {
|
||||
t[i] = new Thread(new DaemonSpawn());
|
||||
@@ -22,6 +26,7 @@ class Daemon implements Runnable {
|
||||
}
|
||||
|
||||
class DaemonSpawn implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
Thread.yield();
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package concurrency;//: concurrency/DaemonsDontRunFinally.java
|
||||
// Daemon threads don't run the finally clause
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
class ADaemon implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
print("Starting ADaemon");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package concurrency;//: concurrency/DeadlockingDiningPhilosophers.java
|
||||
// Demonstrates how deadlock can be hidden in a program.
|
||||
// {Args: 0 5 timeout}
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class DeadlockingDiningPhilosophers {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package concurrency;//: concurrency/DelayQueueDemo.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
@@ -11,16 +13,21 @@ class DelayedTask implements Runnable, Delayed {
|
||||
private final long trigger;
|
||||
protected static List<DelayedTask> sequence =
|
||||
new ArrayList<DelayedTask>();
|
||||
|
||||
public DelayedTask(int delayInMilliseconds) {
|
||||
delta = delayInMilliseconds;
|
||||
trigger = System.nanoTime() +
|
||||
NANOSECONDS.convert(delta, MILLISECONDS);
|
||||
sequence.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDelay(TimeUnit unit) {
|
||||
return unit.convert(
|
||||
trigger - System.nanoTime(), NANOSECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Delayed arg) {
|
||||
DelayedTask that = (DelayedTask) arg;
|
||||
if (trigger < that.trigger) {
|
||||
@@ -31,20 +38,31 @@ class DelayedTask implements Runnable, Delayed {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public void run() { printnb(this + " "); }
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
printnb(this + " ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%1$-4d]", delta) +
|
||||
" Task " + id;
|
||||
}
|
||||
|
||||
public String summary() {
|
||||
return "(" + id + ":" + delta + ")";
|
||||
}
|
||||
|
||||
public static class EndSentinel extends DelayedTask {
|
||||
private ExecutorService exec;
|
||||
|
||||
public EndSentinel(int delay, ExecutorService e) {
|
||||
super(delay);
|
||||
exec = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (DelayedTask pt : sequence) {
|
||||
printnb(pt.summary() + " ");
|
||||
@@ -58,9 +76,12 @@ class DelayedTask implements Runnable, Delayed {
|
||||
|
||||
class DelayedTaskConsumer implements Runnable {
|
||||
private DelayQueue<DelayedTask> q;
|
||||
|
||||
public DelayedTaskConsumer(DelayQueue<DelayedTask> q) {
|
||||
this.q = q;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package concurrency;//: concurrency/EvenChecker.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class EvenChecker implements Runnable {
|
||||
private IntGenerator generator;
|
||||
private final int id;
|
||||
|
||||
public EvenChecker(IntGenerator g, int ident) {
|
||||
generator = g;
|
||||
id = ident;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!generator.isCanceled()) {
|
||||
int val = generator.next();
|
||||
@@ -17,6 +21,7 @@ public class EvenChecker implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test any type of IntGenerator:
|
||||
public static void test(IntGenerator gp, int count) {
|
||||
System.out.println("Press Control-C to exit");
|
||||
@@ -26,6 +31,7 @@ public class EvenChecker implements Runnable {
|
||||
}
|
||||
exec.shutdown();
|
||||
}
|
||||
|
||||
// Default value for count:
|
||||
public static void test(IntGenerator gp) {
|
||||
test(gp, 10);
|
||||
|
||||
@@ -3,11 +3,14 @@ package concurrency;//: concurrency/EvenGenerator.java
|
||||
|
||||
public class EvenGenerator extends IntGenerator {
|
||||
private int currentEvenValue = 0;
|
||||
|
||||
@Override
|
||||
public int next() {
|
||||
++currentEvenValue; // Danger point here!
|
||||
++currentEvenValue;
|
||||
return currentEvenValue;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
EvenChecker.test(new EvenGenerator());
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package concurrency;//: concurrency/ExceptionThread.java
|
||||
// {ThrowsException}
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class ExceptionThread implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ExecutorService exec = Executors.newCachedThreadPool();
|
||||
exec.execute(new ExceptionThread());
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
package concurrency;//: concurrency/ExchangerDemo.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
import net.mindview.util.*;
|
||||
|
||||
class ExchangerProducer<T> implements Runnable {
|
||||
private Generator<T> generator;
|
||||
private Exchanger<List<T>> exchanger;
|
||||
private List<T> holder;
|
||||
|
||||
ExchangerProducer(Exchanger<List<T>> exchg,
|
||||
Generator<T> gen, List<T> holder) {
|
||||
exchanger = exchg;
|
||||
generator = gen;
|
||||
this.holder = holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -32,10 +37,13 @@ class ExchangerConsumer<T> implements Runnable {
|
||||
private Exchanger<List<T>> exchanger;
|
||||
private List<T> holder;
|
||||
private volatile T value;
|
||||
|
||||
ExchangerConsumer(Exchanger<List<T>> ex, List<T> holder) {
|
||||
exchanger = ex;
|
||||
this.holder = holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -55,6 +63,7 @@ class ExchangerConsumer<T> implements Runnable {
|
||||
public class ExchangerDemo {
|
||||
static int size = 10;
|
||||
static int delay = 5; // Seconds
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length > 0) {
|
||||
size = new Integer(args[0]);
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
//: concurrency/ExplicitCriticalSection.java
|
||||
// Using explicit Lock objects to create critical sections.
|
||||
package concurrency;
|
||||
|
||||
import java.util.concurrent.locks.*;
|
||||
|
||||
// Synchronize the entire method:
|
||||
class ExplicitPairManager1 extends PairManager {
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
public synchronized void increment() {
|
||||
lock.lock();
|
||||
try {
|
||||
@@ -21,6 +24,8 @@ class ExplicitPairManager1 extends PairManager {
|
||||
// Use a critical section:
|
||||
class ExplicitPairManager2 extends PairManager {
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
public void increment() {
|
||||
Pair temp;
|
||||
lock.lock();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package concurrency;//: concurrency/FastSimulation.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
public class FastSimulation {
|
||||
@@ -11,7 +13,9 @@ public class FastSimulation {
|
||||
static final AtomicInteger[][] GRID =
|
||||
new AtomicInteger[N_ELEMENTS][N_GENES];
|
||||
static Random rand = new Random(47);
|
||||
|
||||
static class Evolver implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!Thread.interrupted()) {
|
||||
// Randomly select an element to work on:
|
||||
@@ -41,6 +45,7 @@ public class FastSimulation {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ExecutorService exec = Executors.newCachedThreadPool();
|
||||
for (int i = 0; i < N_ELEMENTS; i++) {
|
||||
|
||||
@@ -5,12 +5,20 @@ public class Fat {
|
||||
private volatile double d; // Prevent optimization
|
||||
private static int counter = 0;
|
||||
private final int id = counter++;
|
||||
|
||||
public Fat() {
|
||||
// Expensive, interruptible operation:
|
||||
for (int i = 1; i < 10000; 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;
|
||||
}
|
||||
} ///:~
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package concurrency;//: concurrency/FixedDiningPhilosophers.java
|
||||
// Dining philosophers without deadlock.
|
||||
// {Args: 5 5 timeout}
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class FixedDiningPhilosophers {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package concurrency;//: concurrency/FixedThreadPool.java
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class FixedThreadPool {
|
||||
|
||||
@@ -2,6 +2,7 @@ package concurrency;//: concurrency/GreenhouseScheduler.java
|
||||
// Rewriting innerclasses/GreenhouseController.java
|
||||
// to use a ScheduledThreadPoolExecutor.
|
||||
// {Args: 5000}
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
@@ -9,23 +10,30 @@ public class GreenhouseScheduler {
|
||||
private volatile boolean light = false;
|
||||
private volatile boolean water = false;
|
||||
private String thermostat = "Day";
|
||||
|
||||
public synchronized String getThermostat() {
|
||||
return thermostat;
|
||||
}
|
||||
|
||||
public synchronized void setThermostat(String value) {
|
||||
thermostat = value;
|
||||
}
|
||||
|
||||
ScheduledThreadPoolExecutor scheduler =
|
||||
new ScheduledThreadPoolExecutor(10);
|
||||
|
||||
public void schedule(Runnable event, long delay) {
|
||||
scheduler.schedule(event, delay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void
|
||||
repeat(Runnable event, long initialDelay, long period) {
|
||||
scheduler.scheduleAtFixedRate(
|
||||
event, initialDelay, period, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
class LightOn implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here to
|
||||
// physically turn on the light.
|
||||
@@ -33,7 +41,9 @@ public class GreenhouseScheduler {
|
||||
light = true;
|
||||
}
|
||||
}
|
||||
|
||||
class LightOff implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here to
|
||||
// physically turn off the light.
|
||||
@@ -41,44 +51,59 @@ public class GreenhouseScheduler {
|
||||
light = false;
|
||||
}
|
||||
}
|
||||
|
||||
class WaterOn implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here.
|
||||
System.out.println("Turning greenhouse water on");
|
||||
water = true;
|
||||
}
|
||||
}
|
||||
|
||||
class WaterOff implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here.
|
||||
System.out.println("Turning greenhouse water off");
|
||||
water = false;
|
||||
}
|
||||
}
|
||||
|
||||
class ThermostatNight implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here.
|
||||
System.out.println("Thermostat to night setting");
|
||||
setThermostat("Night");
|
||||
}
|
||||
}
|
||||
|
||||
class ThermostatDay implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here.
|
||||
System.out.println("Thermostat to day setting");
|
||||
setThermostat("Day");
|
||||
}
|
||||
}
|
||||
|
||||
class Bell implements Runnable {
|
||||
public void run() { System.out.println("Bing!"); }
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Bing!");
|
||||
}
|
||||
}
|
||||
|
||||
class Terminate implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Terminating");
|
||||
scheduler.shutdownNow();
|
||||
// Must start a separate task to do this job,
|
||||
// since the scheduler has been shut down:
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (DataPoint d : data) {
|
||||
System.out.println(d);
|
||||
@@ -87,16 +112,20 @@ public class GreenhouseScheduler {
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
||||
// New feature: data collection
|
||||
static class DataPoint {
|
||||
final Calendar time;
|
||||
final float temperature;
|
||||
final float humidity;
|
||||
|
||||
public DataPoint(Calendar d, float temp, float hum) {
|
||||
time = d;
|
||||
temperature = temp;
|
||||
humidity = hum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return time.getTime() +
|
||||
String.format(
|
||||
@@ -104,11 +133,14 @@ public class GreenhouseScheduler {
|
||||
temperature, humidity);
|
||||
}
|
||||
}
|
||||
|
||||
private Calendar lastTime = Calendar.getInstance();
|
||||
|
||||
{ // Adjust date to the half hour
|
||||
lastTime.set(Calendar.MINUTE, 30);
|
||||
lastTime.set(Calendar.SECOND, 00);
|
||||
}
|
||||
|
||||
private float lastTemp = 65.0f;
|
||||
private int tempDirection = +1;
|
||||
private float lastHumidity = 50.0f;
|
||||
@@ -116,7 +148,9 @@ public class GreenhouseScheduler {
|
||||
private Random rand = new Random(47);
|
||||
List<DataPoint> data = Collections.synchronizedList(
|
||||
new ArrayList<DataPoint>());
|
||||
|
||||
class CollectData implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Collecting data");
|
||||
synchronized (GreenhouseScheduler.this) {
|
||||
@@ -143,6 +177,7 @@ public class GreenhouseScheduler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
GreenhouseScheduler gh = new GreenhouseScheduler();
|
||||
gh.schedule(gh.new Terminate(), 5000);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package concurrency;//: concurrency/HorseRace.java
|
||||
// Using CyclicBarriers.
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
class Horse implements Runnable {
|
||||
@@ -10,8 +12,16 @@ class Horse implements Runnable {
|
||||
private int strides = 0;
|
||||
private static Random rand = new Random(47);
|
||||
private static CyclicBarrier barrier;
|
||||
public Horse(CyclicBarrier b) { barrier = b; }
|
||||
public synchronized int getStrides() { return strides; }
|
||||
|
||||
public Horse(CyclicBarrier b) {
|
||||
barrier = b;
|
||||
}
|
||||
|
||||
public synchronized int getStrides() {
|
||||
return strides;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -27,7 +37,12 @@ class Horse implements Runnable {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public String toString() { return "Horse " + id + " "; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Horse " + id + " ";
|
||||
}
|
||||
|
||||
public String tracks() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (int i = 0; i < getStrides(); i++) {
|
||||
@@ -44,8 +59,10 @@ public class HorseRace {
|
||||
private ExecutorService exec =
|
||||
Executors.newCachedThreadPool();
|
||||
private CyclicBarrier barrier;
|
||||
|
||||
public HorseRace(int nHorses, final int pause) {
|
||||
barrier = new CyclicBarrier(nHorses, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (int i = 0; i < FINISH_LINE; i++) {
|
||||
@@ -75,6 +92,7 @@ public class HorseRace {
|
||||
exec.execute(horse);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int nHorses = 7;
|
||||
int pause = 200;
|
||||
|
||||
@@ -2,8 +2,15 @@ package concurrency;//: concurrency/IntGenerator.java
|
||||
|
||||
public abstract class IntGenerator {
|
||||
private volatile boolean canceled = false;
|
||||
|
||||
public abstract int next();
|
||||
|
||||
// Allow this to be canceled:
|
||||
public void cancel() { canceled = true; }
|
||||
public boolean isCanceled() { return canceled; }
|
||||
public void cancel() {
|
||||
canceled = true;
|
||||
}
|
||||
|
||||
public boolean isCanceled() {
|
||||
return canceled;
|
||||
}
|
||||
} ///:~
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user