package Samples; /*Generated by MPS */ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import java.util.concurrent.CountDownLatch; import jetbrains.mps.internal.collections.runtime.Sequence; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import utils.ParallelLoopException; import java.util.concurrent.atomic.AtomicInteger; public class ParallelForSample { public ParallelForSample() { } public static void main(String[] args) { // Some thread pools to use final ExecutorService myPool = Executors.newFixedThreadPool(3); final ExecutorService youPool = Executors.newFixedThreadPool(10); // A collection of numbers to play with final Iterable<Integer> numbers = ListSequence.fromListAndArray(new ArrayList<Integer>(), 1, 2, 3, 4, 5); // The optional reference to a thread pool is set in the Inspector (Alt|Command + 2) { final CountDownLatch latch_i0d = new CountDownLatch(Sequence.fromIterable(numbers).count()); final List<Exception> exceptions_i0d = new CopyOnWriteArrayList<Exception>(); for (final int a : numbers) { final int localA = a; final Runnable runnable = new Runnable() { public void run() { try { log("Starting calculation for number " + localA + " in thread " + Thread.currentThread()); Thread.sleep(localA * 1000); // External (compiled) method calls can be annotated as thread-safe to indicate that they are safe to call log("Finished calculation for number " + localA + " in thread " + Thread.currentThread()); } catch (RuntimeException e) { ListSequence.fromList(exceptions_i0d).addElement(e); } catch (InterruptedException e) { ListSequence.fromList(exceptions_i0d).addElement(e); } finally { latch_i0d.countDown(); } } }; myPool.execute(runnable); } try { latch_i0d.await(); } catch (InterruptedException e) { ListSequence.fromList(exceptions_i0d).addElement(e); } if (ListSequence.fromList(exceptions_i0d).isNotEmpty()) { throw new ParallelLoopException("Some parallel calculations failed", exceptions_i0d); } } log("Done"); // References to non-final variables and parameters from within parallel loops are reported as errors // Try making the following variable non-final (Alt + Enter) final String doNotMessupWith = "The Shared State"; // Accessing non-thread-safe classes, such as lists, is reported as warnings final List<String> names = ListSequence.fromListAndArray(new ArrayList<String>(), "Joe", "Dave", "Alice"); // Accessing thread-safe classes is considered ok final AtomicInteger counter = new AtomicInteger(0); { final CountDownLatch latch_w0d = new CountDownLatch(Sequence.fromIterable(numbers).count()); final List<Exception> exceptions_w0d = new CopyOnWriteArrayList<Exception>(); for (final int b : numbers) { final int localA = b; final Runnable runnable = new Runnable() { public void run() { try { log("Touching " + doNotMessupWith); int messupWithMeSinceImlocal = 1; messupWithMeSinceImlocal += 10; log("Local variables can be used without restrictions " + messupWithMeSinceImlocal); // Warning since we are accessing a non-local non-thread-safe object ListSequence.fromList(names).removeElement("Joe"); List<String> localNames = ListSequence.fromList(new ArrayList<String>()); // Local references can be called without restrictions ListSequence.fromList(localNames).addElement("Susan"); // Thread-safe objects are safe to use as well log("Counter: " + counter.incrementAndGet()); Thread.sleep(localA); } catch (RuntimeException e) { ListSequence.fromList(exceptions_w0d).addElement(e); } catch (InterruptedException e) { ListSequence.fromList(exceptions_w0d).addElement(e); } finally { latch_w0d.countDown(); } } }; youPool.execute(runnable); } try { latch_w0d.await(); } catch (InterruptedException e) { ListSequence.fromList(exceptions_w0d).addElement(e); } if (ListSequence.fromList(exceptions_w0d).isNotEmpty()) { throw new ParallelLoopException("Some parallel calculations failed", exceptions_w0d); } } // Iterating over a collection of strings // No thread pool is set (Alt|Command + 2) so using threads directly { final CountDownLatch latch_ab0d = new CountDownLatch(ListSequence.fromList(names).count()); final List<Exception> exceptions_ab0d = new CopyOnWriteArrayList<Exception>(); for (final String c : names) { final String localA = c; final Runnable runnable = new Runnable() { public void run() { try { log("Name: " + localA); if (localA == "Joe") { throw new RuntimeException("test"); } } catch (RuntimeException e) { ListSequence.fromList(exceptions_ab0d).addElement(e); } finally { latch_ab0d.countDown(); } } }; new Thread(runnable).start(); } try { latch_ab0d.await(); } catch (InterruptedException e) { ListSequence.fromList(exceptions_ab0d).addElement(e); } if (ListSequence.fromList(exceptions_ab0d).isNotEmpty()) { throw new ParallelLoopException("Some parallel calculations failed", exceptions_ab0d); } } // Shutdown the thread pools myPool.shutdown(); youPool.shutdown(); } private static void log(String message) { System.out.println("Logging: " + message); } }