import java.util.Arrays; // for testing purposes only /* This class has a method that copies the elements from one int[] array ** segment into another. (The two segments can be within the same array, ** but in that case they cannot overlap.) It uses threads so that the work ** is done (potentially, at least) in parallel. ** ** Author: R. McCloskey ** Date: November 28, 2020 */ public class ArrayCopierParallel { // class constant // -------------- private static final int LENGTH_THRESHOLD = 2; // instance variable // ----------------- private int[] source; // Source array private int[] dest; // Destination array private int length; // length of relevant segments private int sourceStart; // source[sourceStart..sourceStart+length) is to private int destStart; // be copied into dest[destStart..destStart+length) // Note: The reason for the above being instance variables of this class // is so that (the many) instances of the nested class can access them // without each one needing its own instance variables referring to them. /* Copies the elements in from[fromStart..fromStart+len) into ** to[toStart..toStart+len). ** pre: 0 <= fromStart <= fromStart+len <= from.length && ** 0 <= toStart <= toStart+len <= to.length && */ public void copy(int[] from, int fromStart, int[] to, int toStart, int len) { this.source = from; this.sourceStart = fromStart; this.dest = to; this.destStart = toStart; this.length = len; CopyInParallel copier = new CopyInParallel(0, length); Thread t = new Thread(copier); t.start(); join(t); } /* Letting M be the lesser of from.length and to.length, ** copies the elements of from[0..M) into to[0..M). */ public void copy(int[] from, int[] to) { copy(from, 0, to, 0, Math.min(from.length, to.length)); } /* An instance of this nested class is intended to be used in constructing ** a thread that copies the elements in a segment of source[], where the ** boundaries of that segment are provided as parameters to the constructor, ** into the elements of dest[]. */ private class CopyInParallel implements Runnable { // instance variables // ------------------ int low, len; // Calling copy() on this object results in the elements // of source[sourceStart+low..sourceStart+low+len) // being copied into the corresponding locations within // dest[destStart+low..destStart+low+len). // constructor // ----------- /* Identifies the array segment whose elements are to be copied by ** this object (source[sourceStart+offset..sourceStart+offset+len). ** pre: 0 <= low+start <= low+start+len <= a.length && */ public CopyInParallel(int offset, int len) { this.low = offset; this.len = len; } // run() method // ------------ public void run() { copy(); } // mutator // ------- /* Copies elements of source[sourceStart+low..sourceStart+low+len) into ** the corresponding locations of dest[destStart+low..destStart+low+len). */ private void copy() { //System.out.printf("Copying elements in source[%d..%d) into " + // "dest[%d..%d)\n", // sourceStart+low, sourceStart+low+len, // destStart+low, destStart+low+len); if (len <= LENGTH_THRESHOLD) { // short segment, so copy copySeq(); // its elements sequentially } else { // split segment into halves and compute the ranks in parallel int halfLen = len / 2; CopyInParallel leftCIP = new CopyInParallel(low, halfLen); Thread leftThread = new Thread(leftCIP); leftThread.start(); CopyInParallel rightCIP = new CopyInParallel(low + halfLen, len-halfLen); rightCIP.copy(); // The next three lines are an alternative to the line above; // they create a new thread for the purpose of permuting the // elements in the "right" half of the array segment rather than // letting "this" thread do that job. //Thread rightThread = new Thread(rightCIP); //rightThread.start(); //join(rightThread); join(leftThread); //System.out.printf("Finished copying elements in source[%d..%d) " + // "into dest[%d..%d)\n", // sourceStart+low, sourceStart+low+len, // destStart+low, destStart+low+len); } } /* Copies the elements of source[sourceStart+low..sourceStart+low+len) ** sequentially into the corresponding locations within ** dest[destStart+low..destStart+low+len). */ private void copySeq() { final int j = sourceStart + low; final int k = destStart + low; for (int i = 0; i != len; i++) { dest[k+i] = source[j+i]; } } } // end of private class /* Applies join() to the given thread, catching InterruptedException ** if it is thrown. */ private void join(Thread t) { try { t.join(); } catch (InterruptedException e) { e.printStackTrace(System.out); } } // main() method (for testing purposes) // ------------------------------------ public static void main(String[] args) { int[] fromAry = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }; int[] toAry = new int[35]; System.out.printf("Source Array: %s\n", Arrays.toString(fromAry)); ArrayCopierParallel acp = new ArrayCopierParallel(); System.out.println("Copying..."); acp.copy(fromAry, 4, toAry, 6, 20); System.out.printf("Destination Array: %s\n", Arrays.toString(toAry)); } }