=====Différentes classes===== ====Runnable==== public class T implements Runnable { public void run() { } } public static void main(String[] args) { Thread t1 = new Thread(new T()); t1.start(); } ====Thread==== public class T extends Thread { public void run() { } } public static void main(String[] args) { T t1 = new T(); t1.start(); } ====FutureTask==== Une ''FutureTask'' doit renvoyer un type. Mettre ''Void'' et ''return null'' si le type de retour n'est pas utilisé. ''FutureTask'' s'exécute depuis un ''Executor'' et la valeur de retour est récupérée via la méthode bloquante ''get''. Quand une exception est générée, elle n'est pas remontée au thread principale. Elle est transformée en une ''ExecutionException'' qui sera générée lors de l'appel à ''get''. import java.util.concurrent.FutureTask; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ExecutionException; public class MyClass { public static void main(String args[]) { FutureTask futureTask = new FutureTask (() -> { throw new IOException("OUPS"); }); ExecutorService executor = Executors.newFixedThreadPool(2); executor.execute(futureTask); try { futureTask.get(); } catch (InterruptedException e) { } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("OK"); System.out.println("OK2"); executor.shutdown(); } } Sortie standard : OK OK2 java.util.concurrent.ExecutionException: java.io.IOException: OUPS at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) at MyClass.main(MyClass.java:15) Caused by: java.io.IOException: OUPS at MyClass.lambda$main$0(MyClass.java:10) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:833) Si l'exception doit être remontée au thread principale, il faut créer une classe qui hérite de ''FutureTask'' et surchargée la méthode ''done()'', appeler le ''get()'' avec le try/catch associé et générer une autre exception (''AssertionError'' par exemple). import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; public class MyClass { public static class SecuredFutureTask extends FutureTask { public SecuredFutureTask(Callable callable) { super(callable); } @Override protected void done() { try { get(); } catch (ExecutionException | InterruptedException e) { throw new AssertionError(e); } } } public static void main(String args[]) { FutureTask futureTask = new SecuredFutureTask(() -> { throw new IOException("OUPS"); }); ExecutorService executor = Executors.newFixedThreadPool(2); executor.execute(futureTask); System.out.println("OK"); executor.shutdown(); } } Sortie standard : OK Exception in thread "pool-1-thread-1" java.lang.AssertionError: java.util.concurrent.ExecutionException: java.io.IOException: OUPS at MyClass$SecuredFutureTask.done(MyClass.java:19) at java.base/java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:381) at java.base/java.util.concurrent.FutureTask.setException(FutureTask.java:250) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:269) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: java.util.concurrent.ExecutionException: java.io.IOException: OUPS at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) at MyClass$SecuredFutureTask.done(MyClass.java:17) ... 6 more Caused by: java.io.IOException: OUPS at MyClass.lambda$main$0(MyClass.java:25) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ... 3 more =====Accès concurrent===== class C { synchronized void p(){ } } est équivalent à class C { void p() { synchronized (this){ } } } Le concept consiste à poser un lock sur une instance ou sur une classe. [[https://www.ibm.com/developerworks/java/tutorials/j-concur/j-concur.html|Concurrency in JDK 5.0]] {{ :lang:java:thread:concurrency_in_jdk_5.0_2019-09-30_08_49_25_.html |Archive au 30/09/2019, version du 23/11/2004}} ======Barrières===== ====Semaphore==== Barrière en attente d'un signal. import java.util.concurrent.Semaphore; public class MyClass { public static void main(String args[]) { Semaphore semaphoreAcquisitionReady = new Semaphore(0); new Thread(() -> { try { Thread.sleep(50); } catch (InterruptedException e) {} System.out.println("BEFORE release"); semaphoreAcquisitionReady.release(); System.out.println("AFTER release"); }).start(); System.out.println("BEFORE acquire"); try { semaphoreAcquisitionReady.acquire(); } catch (InterruptedException e) {} System.out.println("AFTER acquire"); semaphoreAcquisitionReady.release(); } } Sortie standard. BEFORE acquire BEFORE release AFTER release AFTER acquire =====Debug===== ====Nommage des threads==== Par défaut, le nom d'un thread est ''Thread-0'' / ''Thread-1''. Si le thread tourne dans un pool : ''pool-1-thread-1''. Dans le cas des threads, cela se fait directement depuis le constructeur. new Thread(() -> {}, "Nom du thread").start(); Dans le cas de ''Runnable'' qui se lancent dans un pool de threads, il faut modifier le nom directement dans la méthode exécutée par le thread. new FutureTask<>(() -> { Thread.currentThread().setName("Nom du thread"); });