soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
-
Upload
soft-shakech -
Category
Technology
-
view
453 -
download
1
description
Transcript of soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
cocktail d’expérience informatiquesGenève 3 & 4 octobre 2011
Seconde édition
Track
Auteur
Session
Java
Julien PONGE
Java SE 7
soft-shake.ch
Java SE 7Julien Ponge
Fork / Join
Project Coin
NIO.2
invokedynamic
(...)
Fork / Join
synchronized
wait()notify()< 5
java.lang.Threadjava.lang.Runnable
Thread thread = new Thread() { public void run() { System.out.println(">>> Hello!"); }}; thread.start();thread.join();
java.util.concurrent
executorsconcurrent queuesconcurrent collectionsatomic variablessynchronization patternsrich locks
5, 6
class Sum implements Callable<Long> { private final long from; private final long to; Sum(long from, long to) { this.from = from; this.to = to; } public Long call() { long acc = 0; for (long i = from; i <= to; i++) { acc = acc + i; } return acc; } }
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Future<Long>> results = executor.invokeAll(asList( new Sum(0, 10), new Sum(100, 1000), new Sum(10000, 1000000)));
for (Future<Long> result : results) { System.out.println(result.get());}
Threads made easy
Concurrency made easier
Parallelism made easier
1.01.11.21.31.4
56
7
n1 n2 n3 n4 n5 n6 n8n7 n9 ... ... ......
sum1 sum2 sum3sum1 + sum2 sum3 + (...)
total sum
Sum of an array
How many occurrences of “java.util.List” in this filesystem tree?
Load into RAM (1 thread)
subfolders: List<Folder>documents: List<Document>
Folderlines: List<String>
Document
Divide & conquer (#cores threads)
SplitFork subtasksJoin subtasksCompose results
Thread managementMaximize parallelism
Work stealing
Your workForkJoinPool
Child ForkJoinTask
fork() fork()join() join()
Child ForkJoinTask
ForkJoinTask
RecursiveActionvs
RecursiveTask
Document wordcounting task
Document wordcounting task
Folder wordcounting task
Folder wordcounting task
Document wordcounting task
Document wordcounting task
3
n
2
51
10
16
fork()
join()
(F/J demo)
1"
2"
3"
4"
5"
6"
7"
2" 4" 6" 8" 10" 12"
Speedup&
#cores
No I/ONo synchronization / locks
Decompose in simple recursive tasksDo not decompose below a threshold
Take advantage of multicores with no pain
You have more F/J candidate algorithms than you think!
try-with-resources
private void writeSomeData() throws IOException { DataOutputStream out = new DataOutputStream(new FileOutputStream("data")); out.writeInt(666); out.writeUTF("Hello"); out.close();}
private void writeSomeData() throws IOException { DataOutputStream out = new DataOutputStream(new FileOutputStream("data")); out.writeInt(666); out.writeUTF("Hello"); out.close();}
what if...
private void writeSomeData() throws IOException { DataOutputStream out = null; try { out = new DataOutputStream(new FileOutputStream("data")); out.writeInt(666); out.writeUTF("Hello"); } finally { if (out != null) { out.close(); } } }
private void writeSomeData() throws IOException { DataOutputStream out = null; try { out = new DataOutputStream(new FileOutputStream("data")); out.writeInt(666); out.writeUTF("Hello"); } finally { if (out != null) { out.close(); } } }
...this is still far from correct!
try (
FileOutputStream out = new FileOutputStream("output"); FileInputStream in1 = new FileInputStream(“input1”); FileInputStream in2 = new FileInputStream(“input2”)
) {
// Do something useful with those 3 streams! // out, in1 and in2 will be closed in any case
out.write(in1.read()); out.write(in2.read());}
public class AutoClose implements AutoCloseable { @Override public void close() { System.out.println(">>> close()"); throw new RuntimeException("Exception in close()"); } public void work() throws MyException { System.out.println(">>> work()"); throw new MyException("Exception in work()"); }}
AutoClose autoClose = new AutoClose();try { autoClose.work();} finally { autoClose.close();}
AutoClose autoClose = new AutoClose();try { autoClose.work();} finally { autoClose.close();}
>>> work() >>> close() java.lang.RuntimeException: Exception in close() at AutoClose.close(AutoClose.java:6) at AutoClose.runWithMasking(AutoClose.java:19) at AutoClose.main(AutoClose.java:52)
AutoClose autoClose = new AutoClose();try { autoClose.work();} finally { autoClose.close();}
>>> work() >>> close() java.lang.RuntimeException: Exception in close() at AutoClose.close(AutoClose.java:6) at AutoClose.runWithMasking(AutoClose.java:19) at AutoClose.main(AutoClose.java:52)
MyException masked by RuntimeException
“Caused by” ≠ “Also happened”
AutoClose autoClose = new AutoClose();MyException myException = null;try { autoClose.work();} catch (MyException e) { myException = e; throw e;} finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); }}
AutoClose autoClose = new AutoClose();MyException myException = null;try { autoClose.work();} catch (MyException e) { myException = e; throw e;} finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); }}
AutoClose autoClose = new AutoClose();MyException myException = null;try { autoClose.work();} catch (MyException e) { myException = e; throw e;} finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); }}
AutoClose autoClose = new AutoClose();MyException myException = null;try { autoClose.work();} catch (MyException e) { myException = e; throw e;} finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); }}
AutoClose autoClose = new AutoClose();MyException myException = null;try { autoClose.work();} catch (MyException e) { myException = e; throw e;} finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); }}
try (AutoClose autoClose = new AutoClose()) { autoClose.work();}
try (AutoClose autoClose = new AutoClose()) { autoClose.work();}
>>> work() >>> close() MyException: Exception in work() at AutoClose.work(AutoClose.java:11) at AutoClose.main(AutoClose.java:16) Suppressed: java.lang.RuntimeException: Exception in close() at AutoClose.close(AutoClose.java:6) at AutoClose.main(AutoClose.java:17)
public void compress(String input, String output) throws IOException { try( FileInputStream fin = new FileInputStream(input); FileOutputStream fout = new FileOutputStream(output); GZIPOutputStream out = new GZIPOutputStream(fout) ) { byte[] buffer = new byte[4096]; int nread = 0; while ((nread = fin.read(buffer)) != -1) { out.write(buffer, 0, nread); } }}
public void compress(String paramString1, String paramString2) throws IOException { FileInputStream localFileInputStream = new FileInputStream(paramString1); Object localObject1 = null; try { FileOutputStream localFileOutputStream = new FileOutputStream(paramString2); Object localObject2 = null; try { GZIPOutputStream localGZIPOutputStream = new GZIPOutputStream(localFileOutputStream); Object localObject3 = null; try { byte[] arrayOfByte = new byte[4096]; int i = 0; while ((i = localFileInputStream.read(arrayOfByte)) != -1) { localGZIPOutputStream.write(arrayOfByte, 0, i); } } catch (Throwable localThrowable6) { localObject3 = localThrowable6; throw localThrowable6; } finally { if (localGZIPOutputStream != null) { if (localObject3 != null) { try { localGZIPOutputStream.close(); } catch (Throwable localThrowable7) { localObject3.addSuppressed(localThrowable7); } } else { localGZIPOutputStream.close(); } } } } catch (Throwable localThrowable4) { localObject2 = localThrowable4; throw localThrowable4; } finally { if (localFileOutputStream != null) { if (localObject2 != null) { try { localFileOutputStream.close(); } catch (Throwable localThrowable8) { localObject2.addSuppressed(localThrowable8); } } else { localFileOutputStream.close(); } } } } catch (Throwable localThrowable2) { localObject1 = localThrowable2; throw localThrowable2; } finally { if (localFileInputStream != null) { if (localObject1 != null) { try { localFileInputStream.close(); } catch (Throwable localThrowable9) { localObject1.addSuppressed(localThrowable9); } } else { localFileInputStream.close(); } } } }
public void compress(String input, String output) throws IOException { try( FileInputStream fin = new FileInputStream(input); FileOutputStream fout = new FileOutputStream(output); GZIPOutputStream out = new GZIPOutputStream(fout) ) { byte[] buffer = new byte[4096]; int nread = 0; while ((nread = fin.read(buffer)) != -1) { out.write(buffer, 0, nread); } }}
Not just syntactic sugarClutter-free, correct code
close(): - be more specific than java.lang.Exception - no exception if it can’t fail - no exception that shall not be suppressed (e.g., java.lang.InterruptedException)
Diamond <>
List<String> strings = new LinkedList<Integer>();
Map<String, List<String>> contacts = new HashMap<Integer, String>();
List<String> strings = new LinkedList<String>();strings.add("hello");strings.add("world");
Map<String, List<String>> contacts = new HashMap<String, List<String>>();contacts.put("Julien", new LinkedList<String>());contacts.get("Julien").addAll(asList("Foo", "Bar", "Baz"));
List<String> strings = new LinkedList<>();strings.add("hello");strings.add("world");
Map<String, List<String>> contacts = new HashMap<>();contacts.put("Julien", new LinkedList<String>());contacts.get("Julien").addAll(asList("Foo", "Bar", "Baz"));
Map<String, String> map = new HashMap<String, String>() { { put("foo", "bar"); put("bar", "baz"); }};
Map<String, String> map = new HashMap<>() { { put("foo", "bar"); put("bar", "baz"); }};
Map<String, String> map = new HashMap<>() { { put("foo", "bar"); put("bar", "baz"); }};
Diamond.java:43: error: cannot infer type arguments for HashMap; Map<String, String> map = new HashMap<>() { ^ reason: cannot use '<>' with anonymous inner classes1 error
class SomeClass<T extends Serializable & CharSequence> { }
Non-denotable type
class SomeClass<T extends Serializable & CharSequence> { }
Non-denotable type
SomeClass<?> foo = new SomeClass<String>();SomeClass<?> fooInner = new SomeClass<String>() { };
SomeClass<?> bar = new SomeClass<>();
SomeClass<?> bar = new SomeClass<>() { };
class SomeClass<T extends Serializable & CharSequence> { }
Non-denotable type
SomeClass<?> foo = new SomeClass<String>();SomeClass<?> fooInner = new SomeClass<String>() { };
SomeClass<?> bar = new SomeClass<>();
SomeClass<?> bar = new SomeClass<>() { };
No denotable typeto generate a class
Less ceremony when using generics
No diamond with inner classes
Simplified varargs
private static <T> void doSomethingBad(List<T> list, T... values) { values[0] = list.get(0);}
public static void main(String[] args) { List list = Arrays.asList("foo", "bar", "baz"); doSomethingBad(list, 1, 2, 3);}
private static <T> void doSomethingBad(List<T> list, T... values) { values[0] = list.get(0);}
public static void main(String[] args) { List list = Arrays.asList("foo", "bar", "baz"); doSomethingBad(list, 1, 2, 3);}
Heap Pollution: List = List<String>
This yields warnings + crash:
private static <T> void doSomethingGood(List<T> list, T... values) { for (T value : values) { list.add(value); }}
private static <T> void doSomethingGood(List<T> list, T... values) { for (T value : values) { list.add(value); }}
$ javac Good.java Note: Good.java uses unchecked or unsafe operations.Note: Recompile with -Xlint:unchecked for details.
@SuppressWarnings({“unchecked”,“varargs”})
public static void main(String[] args) { List<String> list = new LinkedList<>(); doSomethingGood(list, "hi", "there", "!");}
$ javac Good.java $
@SafeVarargsprivate static <T> void doSomethingGood(List<T> list, T... values) { for (T value : values) { list.add(value); }}
static, final methods, constructors
Mark your code as safe for varargs
You can’t cheat with @SafeVarags
Remove @SuppressWarnings in client code and pay attention to real warnings
Multi-catch & more precise rethrow
Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance));
try { Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance));} catch (ClassNotFoundException e) { e.printStackTrace();} catch (InstantiationException e) { e.printStackTrace();} catch (IllegalAccessException e) { e.printStackTrace();} catch (NoSuchMethodException e) { e.printStackTrace();} catch (InvocationTargetException e) { e.printStackTrace();}
try { Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance));} catch (Throwable t) { t.printStackTrace();}
try { Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance));} catch (Throwable t) { t.printStackTrace();}
How about SecurityException?
try { Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance));} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace();}
Union of alternatives
catch (SomeException e)
Now implicitly final unless assigned...
static class SomeRootException extends Exception { }static class SomeChildException extends SomeRootException { }static class SomeOtherChildException extends SomeRootException { }
public static void main(String... args) throws Throwable {try { throw new SomeChildException();} catch (SomeRootException firstException) { try { throw firstException; } catch (SomeOtherChildException secondException) { System.out.println("I got you!"); }}
static class SomeRootException extends Exception { }static class SomeChildException extends SomeRootException { }static class SomeOtherChildException extends SomeRootException { }
public static void main(String... args) throws Throwable {try { throw new SomeChildException();} catch (SomeRootException firstException) { try { throw firstException; } catch (SomeOtherChildException secondException) { System.out.println("I got you!"); }}
$ javac Imprecise.java Imprecise.java:13: error: exception SomeOtherChildException is never thrown in body of corresponding try statement } catch (SomeOtherChildException secondException) { ^1 error
Less clutterBe preciseDo not capture unintended exceptions
Better exception flow analysis
Minor additions
// 123 in decimal, octal, hexadecimal and binarybyte decimal = 123;byte octal = 0_173;byte hexadecimal = 0x7b;byte binary = 0b0111_1011;
// Other valuesdouble doubleValue = 1.111_222_444F;long longValue = 1_234_567_898L;long longHexa = 0x1234_3b3b_0123_cdefL;
public static boolean isTrue(String str) { switch(str.trim().toUpperCase()) { case "OK": case "YES": case "TRUE": return true;
case "KO": case "NO": case "FALSE": return false;
default: throw new IllegalArgumentException("Not a valid true/false string."); } }
public static boolean isTrue(String s) { String str = s.trim().toUpperCase(); int jump = -1; switch(str.hashCode()) { case 2404: if (str.equals("KO")) { jump = 3; } break;(...) switch(jump) {(...) case 3: case 4: case 5: return false; default: throw new IllegalArgumentException( "Not a valid true/false string."); }}
Bucket
Real code
Fork and Join: Java Can Excel at Painless Parallel Programming Too!
Better Resource Management withJava SE 7: Beyond Syntactic Sugar
Oracle Technology Network
http://goo.gl/tostz
http://goo.gl/7ybgr
(more soon...)
Julien Ponge
@jponge
http://gplus.to/jponge
http://julien.ponge.info/