Upload
julienponge
View
742
Download
0
Tags:
Embed Size (px)
Citation preview
LavaJUG
Java 7 — Julien Ponge@jponge
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)
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()
SplitFork subtasksJoin subtasksCompose results
Thread managementMaximize parallelism
Work stealing
Your workForkJoinPool
Child ForkJoinTask
fork() fork()join() join()
Child ForkJoinTask
ForkJoinTask
RecursiveActionvs
RecursiveTask
(Some F/J Code)
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/