Programmer II Chapter 6: Concurrency Flashcards

1
Q

What does this code output?

List favNumbers =
new CopyOnWriteArrayList < > (List.of(4,3,42));

for(var n: favNumbers) {
System.out.print(n + “ “);
favNumbers.add(9);
}

System.out.println();
System.out.println(“Size: “ + favNumbers.size());

A

4 3 42
Size: 6

Despite adding elements to the array while iterating over it, the for loop only iterated on the ones created when the loop started. Alternatively, if we had used a regular ArrayList object, a ConcurrentModificationException would have been thrown at runtime. With either class, though, we avoid entering an infinite loop in which elements are constantly added to the array as we iterate over them.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Given an instance of a Stream s and a Collection c, which are valid ways of creating a parallel stream? (Choose all that apply.)

A. new ParallelStream(s)
B. c.parallel()
C. s.parallelStream()
D. c.parallelStream()
E. new ParallelStream(c)
F. s.parallel()
A
D, F. 
There is no such class within the Java API called ParallelStream, so options A and E are incorrect. The method defined in the Stream class to create a parallel stream from an existing stream is parallel(); therefore, option F is correct, and option C is incorrect. The method defined in the Collection class to create a parallel stream from a collection is parallelStream(); therefore, option D is correct, and option B is incorrect.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Given that the sum of the numbers from 1 (inclusive) to 10 (exclusive) is 45, what are the possible results of executing the following program? (Choose all that apply.)

import java.util.concurrent.locks.*;
import java.util.stream.*;
    public class Bank {
       private Lock vault = new ReentrantLock();
       private int total = 0;
       public void deposit(int value) {
          try {
             vault.tryLock();
             total += value;
          } finally {
             vault.unlock();
          }
       }
       public static void main(String[] unused) {
          var bank = new Bank();
          IntStream.range(1, 10).parallel()
             .forEach(s -> bank.deposit(s));
          System.out.println(bank.total);
       } 
}
A. 45 is printed.
B. A number less than 45 is printed.
C. A number greater than 45 is printed.
D. An exception is thrown.
E. None of the above, as the code does not compile
A
A, D. 
The tryLock() method returns immediately with a value of false if the lock cannot be acquired. Unlike lock(), it does not wait for a lock to become available. This code fails to check the return value, resulting in the protected code being entered regardless of whether the lock is obtained.In some executions (when tryLock() returns true on every call), the code will complete successfully and print 45 at runtime, making option A correct. On other executions (when tryLock() returns false at least once), the unlock() method will throw an IllegalMonitorStateException at runtime, making option D correct. Option B would be possible if there was no lock at all, although in this case, failure to acquire a lock results in an exception at runtime
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Which of the following statements about the Callable call() and Runnable run() methods are correct? (Choose all that apply.)

A. Both can throw unchecked exceptions.
B. Callable takes a generic method argument.
C. Callable can throw a checked exception.
D. Both can be implemented with lambda expressions.
E. Runnable returns a generic type.
F. Callable returns a generic type.
G. Both methods return void.

A

A, C, D, F.
All methods are capable of throwing unchecked exceptions, so option A is correct. Runnable and Callable statements both do not take any arguments, so option B is incorrect. Only Callable is capable of throwing checked exceptions, so option C is also correct. Both Runnable and Callable are functional interfaces that can be implemented with a lambda expression, so option D is also correct. Finally, Runnable returns void and Callable returns a generic type, making option F correct and making options E and G incorrect.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Which lines need to be changed to make the code compile? (Choose all that apply.)

    ExecutorService service =   // w1
       Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(() -> {
   System.out.println("Open Zoo");
   return null;   // w2
}, 0, 1, TimeUnit.MINUTES);
    var result = service.submit(() ->   // w3
       System.out.println("Wake Staff"));
System.out.println(result.get());   // w4
A. It compiles and runs without issue.
B. Line w1
C. Line w2
D. Line w3
E. Line w4
F. It compiles but throws an exception at runtime.G. None of the above
A

B, C.
The code does not compile, so options A and F are incorrect. The first problem is that although a ScheduledExecutorService is created, it is assigned to an ExecutorService. The type of the variable on line w1 would have to be updated to ScheduledExecutorService for the code to compile,making option B correct. The second problem is that scheduleWithFixedDelay() supports only Runnable, not Callable, and any attempt to return a value is invalid in a Runnable lambda expression; therefore, line w2 will also not compile, and option C is correct. The rest of the lines compile without issue, so options D and E are incorrect.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What statement about the following code is true?

var value1 = new AtomicLong(0);
final long[] value2 = {0};
IntStream.iterate(1, i -> 1).limit(100).parallel()
   .forEach(i -> value1.incrementAndGet());
IntStream.iterate(1, i -> 1).limit(100).parallel()
   .forEach(i -> ++value2[0]);
System.out.println(value1+" "+value2[0]);

A. It outputs 100 100.
B. It outputs 100 99.
C. The output cannot be determined ahead of time.
D. The code does not compile.
E. It compiles but throws an exception at runtime.
F. It compiles but enters an infinite loop at runtime.
G. None of the above

A

C.
The code compiles and runs without throwing an exception or entering an infinite loop, so options D, E, and F are incorrect. The key here is that the increment operator ++ is not atomic. While the first part of the output will always be 100, the second part is nondeterministic. It could output any value from 1 to 100, because the threads can overwrite each other’s work. Therefore, option C is the correct answer, and options A and B are incorrect.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Which statements about the following code are correct? (Choose all that apply.)

    public static void main(String[] args) throws Exception {       var data = List.of(2,5,1,9,8);
       data.stream().parallel()
          .mapToInt(s -> s)
          .peek(System.out::println)
          .forEachOrdered(System.out::println);
    }

A. The peek() method will print the entries in the order: 1 2 5 8 9.
B. The peek() method will print the entries in the order: 2 5 1 9 8.
C. The peek() method will print the entries in an order that cannot be determined ahead of time.
D. The forEachOrdered() method will print the entries in the order: 1 2 5 8 9.
E. The forEachOrdered() method will print the entries in the order: 2 5 1 9 8.
F. The forEachOrdered() method will print the entries in an order that cannot be determined ahead of time.
G. The code does not compile

A

C, E.
The code compiles, so option G is incorrect. The peek() method on a parallel stream will process the elements concurrently, so the order cannot be determined ahead of time, and option C is correct. The forEachOrdered() method will process the elements in the order they are stored in the stream, making option E correct. It does not sort the elements, so option D is incorrect.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Fill in the blanks:___________ occur(s) when two or more threads are blocked forever but both appear active.___________ occur(s) when two or more threads try to complete a related task at the same time, resulting in invalid or unexpected data.

A. Livelock, Deadlock
B. Deadlock, Starvation
C. Race conditions, Deadlock
D. Livelock, Race conditions
E. Starvation, Race conditions
F. Deadlock, Livelock
A

D.
Livelock occurs when two or more threads are conceptually blocked forever, although they areeach still active and trying to complete their task. A race condition is an undesirable result that occurswhen two tasks are completed at the same time, which should have been completed sequentially.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Assuming this class is accessed by only a single thread at a time, what is the result of calling the countIceCreamFlavors() method?

    import java.util.stream.LongStream;
     public class Flavors {
       private static int counter;
       public static void countIceCreamFlavors()  {
          counter = 0;
          Runnable task = () -> counter++;
          LongStream.range(1, 500)
             .forEach(m -> new Thread(task).run());
          System.out.println(counter);
       }
    }

A. The method consistently prints 499.
B. The method consistently prints 500.
C. The method compiles and prints a value, but that value cannot be determined ahead of time.
D. The method does not compile.
E. The method compiles but throws an exception at runtime.
F. None of the above

A

A.
The method looks like it executes a task concurrently, but it actually runs synchronously. In eachiteration of the forEach() loop, the process waits for the run() method to complete before movingon. For this reason, the code is actually thread-safe. It executes a total of 499 times, since the secondvalue of range() excludes the 500. Since the program consistently prints 499 at runtime, option A iscorrect. Note that if start() had been used instead of run() (or the stream was parallel), then theoutput would be indeterminate, and option C would have been correct.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Which happens when a new task is submitted to an ExecutorService, in which there are no threads available?

A. The executor throws an exception when the task is submitted.
B. The executor discards the task without completing it.
C. The executor adds the task to an internal queue and completes when there is an available thread.
D. The thread submitting the task waits on the submit call until a thread is available beforecontinuing.
E. The executor creates a new temporary thread to complete the task

A

C.
If a task is submitted to a thread executor, and the thread executor does not have any availablethreads, the call to the task will return immediately with the task being queued internally by the threadexecutor. For this reason, option C is the correct answer.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What is the result of executing the following code snippet?

List lions = new ArrayList < > (List.of(1,2,3));
List tigers = new CopyOnWriteArrayList < > (lions);
Set < Integer >  bears = new ConcurrentSkipListSet < > ();
bears.addAll(lions);

for(Integer item: tigers) tigers.add(4); // x1
for(Integer item: bears) bears.add(5); // x2
System.out.println(lions.size() + " " + tigers.size()
    \+ " " + bears.size());

A. It outputs 3 6 4.
B. It outputs 6 6 6.
C. It outputs 6 3 4.
D. The code does not compile.
E. It compiles but throws an exception at runtime on line x1.
F. It compiles but throws an exception at runtime on line x2.
G. It compiles but enters an infinite loop at runtime.

A
A. 
The code compiles without issue, so option D is incorrect. The CopyOnWriteArrrayList class is designed to preserve the original list on iteration, so the first loop will be executed exactly three timesand, in the process, will increase the size of tigers to six elements. The ConcurrentSkipListSetclass allows modifications, and since it enforces uniqueness of its elements, the value 5 is added onlyonce leading to a total of four elements in bears. Finally, despite using the elements of lions topopulate the collections, tigers and bears are not backed by the original list, so the size of lions is 3throughout this program. For these reasons, the program prints 3 6 4, and option A is correct.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What statements about the following code are true? (Choose all that apply.)

Integer i1 = List.of(1, 2, 3, 4, 5).stream().findAny().get();    synchronized(i1) { // y1
   Integer i2 = List.of(6, 7, 8, 9, 10)
      .parallelStream()
      .sorted()
      .findAny().get(); // y2
   System.out.println(i1 + " " + i2);
}

A. The first value printed is always 1.
B. The second value printed is always 6.
C. The code will not compile because of line y1.
D. The code will not compile because of line y2.
E. The code compiles but throws an exception at runtime.
F. The output cannot be determined ahead of time.
G. It compiles but waits forever at runtime.

A

F.
The code compiles and runs without issue, so options C, D, E, and G are incorrect. There are twoimportant things to notice. First, synchronizing on the first variable doesn’t actually impact the resultsof the code. Second, sorting on a parallel stream does not mean that findAny() will return the firstrecord. The findAny() method will return the value from the first thread that retrieves a record.Therefore, the output is not guaranteed, and option F is correct. Option A looks correct, but even onserial streams, findAny() is free to select any element.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Assuming takeNap() is a method that takes five seconds to execute without throwing an exception,what is the expected result of executing the following code snippet?

ExecutorService service = null;
try {
   service = Executors.newFixedThreadPool(4);
   service.execute(() -> takeNap());
   service.execute(() -> takeNap());
   service.execute(() -> takeNap());
} finally {
   if (service != null) service.shutdown();
}
service.awaitTermination(2, TimeUnit.SECONDS);
System.out.println("DONE!");

A. It will immediately print DONE!.
B. It will pause for 2 seconds and then print DONE!.
C. It will pause for 5 seconds and then print DONE!.
D. It will pause for 15 seconds and then print DONE!.
E. It will throw an exception at runtime.
F. None of the above, as the code does not compile

A

B.
The code snippet submits three tasks to an ExecutorService, shuts it down, and then waits for theresults. The awaitTermination() method waits a specified amount of time for all tasks to complete,and the service to finish shutting down. Since each five-second task is still executing, theawaitTermination() method will return with a value of false after two seconds but not throw anexception. For these reasons, option B is correct.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What statements about the following code are true? (Choose all that apply.)

System.out.print(List.of("duck","flamingo","pelican")
   .parallelStream().parallel()   // q1
   .reduce(0,
      (c1, c2) -> c1.length() + c2.length(),   // q2
      (s1, s2) -> s1 + s2));   // q3

A. It compiles and runs without issue, outputting the total length of all strings in the stream.
B. The code will not compile because of line q1.
C. The code will not compile because of line q2.
D. The code will not compile because of line q3.
E. It compiles but throws an exception at runtime.
F. None of the above

A

C.
The code does not compile, so options A and E are incorrect. The problem here is that c1 is an intand c2 is a String, so the code fails to combine on line q2, since calling length() on an int is notallowed, and option C is correct. The rest of the lines compile without issue. Note that callingparallel() on an already parallel stream is allowed, and it may in fact return the same object.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What statements about the following code snippet are true? (Choose all that apply.)

    Object o1 = new Object();
    Object o2 = new Object();
    var service = Executors.newFixedThreadPool(2);
    var f1 = service.submit(() -> {
       synchronized (o1) {
          synchronized (o2) { System.out.print("Tortoise"); }
       }
    });
    var f2 = service.submit(() -> {
       synchronized (o2) {
          synchronized (o1) { System.out.print("Hare"); }
       }
    });
f1. get();
f2. get();

A. The code will always output Tortoise followed by Hare.
B. The code will always output Hare followed by Tortoise.
C. If the code does output anything, the order cannot be determined.
D. The code does not compile.
E. The code compiles but may produce a deadlock at runtime.
F. The code compiles but may produce a livelock at runtime.
G. It compiles but throws an exception at runtime.

A

C, E.
The code compiles without issue, so option D is incorrect. Since both tasks are submitted to thesame thread executor pool, the order cannot be determined, so options A and B are incorrect, and
option C is correct. The key here is that the order in which the resources o1 and o2 are synchronizedcould result in a deadlock. For example, if the first thread gets a lock on o1 and the second thread getsa lock on o2 before either thread can get their second lock, then the code will hang at runtime, makingoption E correct. The code cannot produce a livelock, since both threads are waiting, so option F isincorrect. Finally, if a deadlock does occur, an exception will not be thrown, so option G is incorrect.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Which statement about the following code snippet is correct?

2: var cats = Stream.of("leopard", "lynx", "ocelot", "puma")
3: .parallel();
4: var bears = Stream.of("panda","grizzly","polar").parallel();
5: var data = Stream.of(cats,bears).flatMap(s -> s)
6: .collect(Collectors.groupingByConcurrent(
7: s -> !s.startsWith("p")));
8: System.out.println(data.get(false).size()
9: + " " + data.get(true).size());

A. It outputs 3 4.
B. It outputs 4 3.
C. The code will not compile because of line 6.
D. The code will not compile because of line 7.
E. The code will not compile because of line 8.
F. It compiles but throws an exception at runtime

A

A.
The code compiles and runs without issue, so options C, D, E, and F are incorrect. The collect()operation groups the animals into those that do and do not start with the letter p. Note that there arefour animals that do not start with the letter p and three animals that do. The logical complementoperator (!) before the startsWith() method means that results are reversed, so the output is 3 4 andoption A is correct, making option B incorrect.

17
Q

Which statements about methods in ReentrantLock are correct? (Choose all that apply.)

A. The lock() method will attempt to acquire a lock without waiting indefinitely for it.
B. The testLock() method will attempt to acquire a lock without waiting indefinitely for it.
C. The attemptLock() method will attempt to acquire a lock without waiting indefinitely for it.
D. By default, a ReentrantLock fairly releases to each thread, in the order that it was requested.
E. Calling the unlock() method once will release a resource so that other threads can obtain thelock.
F. None of the above

A
F. 
The lock() method will wait indefinitely for a lock, so option A is incorrect. Options B and C arealso incorrect, as the correct method name to attempt to acquire a lock is tryLock(). Option D isincorrect, as fairness is set to false by default and must be enabled by using an overloadedconstructor. Finally, option E is incorrect because a thread that holds the lock may have called lock()or tryLock() multiple times. A thread needs to call unlock() once for each call to lock() andtryLock()
18
Q

What is the result of calling the following method?

3: public void addAndPrintItems(BlockingQueue < Integer >  queue) {
4: queue.offer(103);
5: queue.offer(20, 1, TimeUnit.SECONDS);
6: queue.offer(85, 7, TimeUnit.HOURS);
7: System.out.print(queue.poll(200, TimeUnit.NANOSECONDS));
8: System.out.print(" " + queue.poll(1, TimeUnit.MINUTES));
9: }

A. It outputs 20 85.
B. It outputs 103 20.
C. It outputs 20 103.
D. The code will not compile.
E. It compiles but throws an exception at runtime.
F. The output cannot be determined ahead of time.G. None of the above

A

D.
The methods on line 5, 6, 7, and 8 each throw InterruptedException, which is a checkedexception; therefore, the method does not compile, and option D is the only correct answer. IfInterruptedException was declared in the method signature on line 3, then the answer would beoption F, because adding items to the queue may be blocked at runtime. In this case, the queue ispassed into the method, so there could be other threads operating on it. Finally, if the operations werenot blocked and there were no other operations on the queue, then the output would be 103 20, andthe answer would be option B.

19
Q

Which of the following are valid Callable expressions? (Choose all that apply.)

A. a -> {return 10;}
B. () -> {String s = "";}
C. () -> 5
D. () -> {return null}
E. () -> "The" + "Zoo"
F. (int count) -> count+1
G. () -> {System.out.println("Giraffe"); return 10;}
A

C, E, G.
A Callable lambda expression takes no values and returns a generic type; therefore, options C, E, and G are correct. Options A and F are incorrect because they both take an input parameter.Option B is incorrect because it does not return a value. Option D is not a valid lambda expression,because it is missing a semicolon at the end of the return statement, which is required when inside braces {}.

20
Q

What is the result of executing the following application? (Choose all that apply.)

    import java.util.concurrent.*;
    import java.util.stream.*;
    public class PrintConstants {
       public static void main(String[] args) {
          var s = Executors.newScheduledThreadPool(10);
          DoubleStream.of(3.14159,2.71828)   // b1             .forEach(c -> s.submit(  // b2
                () -> System.out.println(10*c)));   // b3
          s.execute(() -> System.out.println("Printed"));   // b4
       }
    }

A. It compiles and outputs the two numbers, followed by Printed.
B. The code will not compile because of line b1.
C. The code will not compile because of line b2.
D. The code will not compile because of line b3.
E. The code will not compile because of line b4.
F. It compiles, but the output cannot be determined ahead of time.
G. It compiles but throws an exception at runtime.
H. It compiles but waits forever at runtime.

A

F, H.
The application compiles and does not throw an exception, so options B, C, D, E, and G areincorrect. Even though the stream is processed in sequential order, the tasks are submitted to a threadexecutor, which may complete the tasks in any order. Therefore, the output cannot be determinedahead of time, and option F is correct. Finally, the thread executor is never shut down; therefore, thecode will run but it will never terminate, making option H also correct.

21
Q

What is the result of executing the following program? (Choose all that apply.)

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;
    public class PrintCounter {
       static int count = 0;
       public static void main(String[] args) throws                          InterruptedException, ExecutionException {
          ExecutorService service = null;
      try {
         service = Executors.newSingleThreadExecutor();
         var r = new ArrayList < Future < ? > > ();
         IntStream.iterate(0,i -> i+1).limit(5).forEach(
            i -> r.add(service.execute(() -> {count++;})) // n1
         );

         for(Future> result : r) {
            System.out.print(result.get()+" "); // n2
         }

      } finally {
         if(service != null) service.shutdown();
      } } }

A. It prints 0 1 2 3 4.
B. It prints 1 2 3 4 5.
C. It prints null null null null null.
D. It hangs indefinitely at runtime.
E. The output cannot be determined.
F. The code will not compile because of line n1.
G. The code will not compile because of line n2.

A

F.
The key to solving this question is to remember that the execute() method returns void, not a Future object. Therefore, line n1 does not compile, and option F is the correct answer. If the submit() method had been used instead of execute(), then option C would have been the correct answer, as the output of the submit(Runnable) task is a Future < ? > object that can only return null on its get() method.

22
Q

Given the following code snippet and blank lines on p1 and p2, which values guarantee 1 is printed at runtime? (Choose all that apply.)

    var data = List.of(List.of(1,2),
       List.of(3,4),
       List.of(5,6));
    data.\_\_\_\_\_\_\_\_\_\_\_   // p1
       .flatMap(s -> s.stream())
       .\_\_\_\_\_\_\_\_\_\_\_\_ // p2
       .ifPresent(System.out::print);

A. stream() on line p1, findFirst() on line p2.
B. stream() on line p1, findAny() on line p2.
C. parallelStream() in line p1, findAny() on line p2.
D. parallelStream() in line p1, findFirst() on line p2.
E. The code does not compile regardless of what is inserted into the blank.
F. None of the above

A
A, D. 
The findFirst() method guarantees the first element in the stream will be returned, whether itis serial or parallel, making options A and D correct. While option B may consistently print 1 atruntime, the behavior of findAny() on a serial stream is not guaranteed, so option B is incorrect.Option C is likewise incorrect, with the output being random at runtime. Option E is incorrect becauseany of the previous options will allow the code to compile
23
Q

Assuming 100 milliseconds is enough time for the tasks submitted to the service executor to complete,what is the result of executing the following method? (Choose all that apply.)

    private AtomicInteger s1 = new AtomicInteger(0); // w1
    private int s2 = 0;
    private void countSheep() throws InterruptedException {
       ExecutorService service = null;
       try {
          service = Executors.newSingleThreadExecutor(); // w2
          for (int i = 0; i < 100; i++)
             service.execute(() -> {
                s1.getAndIncrement(); s2++; }); // w3
          Thread.sleep(100);
          System.out.println(s1 + " " + s2);
       } finally {
          if(service != null) service.shutdown();
       }
    }

A. The method consistently prints 100 99.
B. The method consistently prints 100 100.
C. The output cannot be determined ahead of time.
D. The code will not compile because of line w1.
E. The code will not compile because of line w2.
F. The code will not compile because of line w3.
G. It compiles but throws an exception at runtime.

A

B.
The code compiles and runs without issue, so options D, E, F, and G are incorrect. The key aspectto notice in the code is that a single-thread executor is used, meaning that no task will be executedconcurrently. Therefore, the results are valid and predictable with 100 100 being the output, andoption B is the correct answer. If a pooled thread executor was used with at least two threads, then thesheepCount2++ operations could overwrite each other, making the second value indeterminate at theend of the program. In this case, option C would be the correct answer.

24
Q

What is the result of executing the following application? (Choose all that apply.)

import java.util.concurrent.*;
import java.util.stream.*;
    public class StockRoomTracker {
       public static void await(CyclicBarrier cb) { // j1
          try { cb.await(); } catch (Exception e) {}
       }
   public static void main(String[] args) {
      var cb = new CyclicBarrier(10,
         () -> System.out.println("Stock Room Full!")); // j2
      IntStream.iterate(1, i -> 1).limit(9).parallel()
         .forEach(i -> await(cb)); // j3
   }
}

A. It outputs Stock Room Full!
B. The code will not compile because of line j1.
C. The code will not compile because of line j2.
D. The code will not compile because of line j3.
E. It compiles but throws an exception at runtime.
F. It compiles but waits forever at runtime.

A

F.
The code compiles without issue, so options B, C, and D are incorrect. The limit on the cyclicbarrier is 10, but the stream can generate only up to 9 threads that reach the barrier; therefore, the limitcan never be reached, and option F is the correct answer, making options A and E incorrect. Even ifthe limit(9) statement was changed to limit(10), the program could still hang since the JVM mightnot allocate 10 threads to the parallel stream.

25
Q

What statements about the following class definition are true? (Choose all that apply.)

    public class TicketManager {
       private int tickets;
       private static TicketManager instance;
       private TicketManager() {}
       static synchronized TicketManager getInstance() {      // k1
          if (instance==null) instance = new TicketManager(); // k2
          return instance;
       }
   public int getTicketCount() { return tickets; }

   public void addTickets(int value) {tickets += value;}  // k3
       public void sellTickets(int value) {
          synchronized (this) { // k4
             tickets -= value;
          }
       }
    }

A. It compiles without issue.
B. The code will not compile because of line k2.
C. The code will not compile because of line k3.
D. The locks acquired on k1 and k4 are on the same object.
E. The class correctly protects the tickets data from race conditions.
F. At most one instance of TicketManager will be created in an application that uses this class.

A
A, F. 
The class compiles without issue, so option A is correct, and options B and C are incorrect.Since getInstance() is a static method and sellTickets() is an instance method, lines k1 and k4synchronize on different objects, making option D incorrect. The class is not thread-safe because theaddTickets() method is not synchronized, and option E is incorrect. For example, one thread couldcall sellTickets() while another thread calls addTickets(). These methods are not synchronizedwith each other and could cause an invalid number of tickets due to a race condition.Finally, option F is correct because the getInstance() method is synchronized. Since theconstructor is private, this method is the only way to create an instance of TicketManager outsidethe class. The first thread to enter the method will set the instance variable, and all other threads willuse the existing value. This is actually a singleton pattern.
26
Q

Which of the following properties of concurrency are true? (Choose all that apply.)

A. By itself, concurrency does not guarantee which task will be completed first.
B. Concurrency always improves the performance of an application.
C. A computer with a single-processor CPU does not benefit from concurrency.
D. Applications with many resource-heavy tasks tend to benefit more from concurrency than ones with CPU-intensive tasks.
E. Concurrent tasks do not share the same memory.

A

A, D.
By itself, concurrency does not guarantee which task will be completed first, so option A iscorrect. Furthermore, applications with numerous resource requests will often be stuck waiting for aresource, which allows other tasks to run. Therefore, they tend to benefit more from concurrency thanCPU-intensive tasks, so option D is also correct. Option B is incorrect because concurrency may infact make an application slower if it is truly single-threaded in nature. Keep in mind that there is a costassociated with allocating additional memory and CPU time to manage the concurrent process. OptionC is incorrect because single-processor CPUs have been benefiting from concurrency for decades.Finally, option E is incorrect; there are numerous examples in this chapter of concurrent tasks sharingmemory.

27
Q

Assuming an implementation of the performCount() method is provided prior to runtime, which ofthe following are possible results of executing the following application? (Choose all that apply.)

    import java.util.*;
    import java.util.concurrent.*;
    public class CountZooAnimals {
       public static void performCount(int animal) {
          // IMPLEMENTATION OMITTED
       }
   public static void printResults(Future < ? >  f) {
      try {
         System.out.println(f.get(1, TimeUnit.DAYS)); // o1
      } catch (Exception e) {
         System.out.println("Exception!");
      }
   }
       public static void main(String[] args) throws Exception {
          ExecutorService s = null;
          final var r = new ArrayList < Future < ? > > ();
          try {
             s = Executors.newSingleThreadExecutor();
             for(int i = 0; i < 10; i++) {
                final int animal = i;
                r.add(s.submit(() -> performCount(animal))); // o2
             }
             r.forEach(f -> printResults(f));
      } finally {
         if(s != null) s.shutdown();
      } } }

A. It outputs a number 10 times.
B. It outputs a Boolean value 10 times.
C. It outputs a null value 10 times.
D. It outputs Exception! 10 times.
E. It hangs indefinitely at runtime.
F. The code will not compile because of line o1.
G. The code will not compile because of line o2

A

C, D.
The code compiles and runs without issue, so options F and G are incorrect. The return type ofperformCount() is void, so submit() is interpreted as being applied to a Runnable expression.While submit(Runnable) does return a Future < ? > , calling get() on it always returns null. For thisreason, options A and B are incorrect, and option C is correct. The performCount() method can alsothrow a runtime exception, which will then be thrown by the get() call as an ExecutionException;therefore, option D is also a correct answer. Finally, it is also possible for our performCount() tohang indefinitely, such as with a deadlock or infinite loop. Luckily, the call to get() includes atimeout value. While each call to Future.get() can wait up to a day for a result, it will eventuallyfinish, so option E is incorrect.