Biblioteca Java - Blame information for rev 28
Subversion Repositories:
Rev | Author | Line No. | Line |
---|---|---|---|
28 | mihai | 1 | package exemple.exchanger; |
2 | |||
3 | import java.util.*; | ||
4 | import java.util.concurrent.*; | ||
5 | |||
6 | /* | ||
7 | * Exchanger offers a simplified way of communicating between threads, that is, by passing | ||
8 | * a specific object between two threads. That's why there's the <V> after the class | ||
9 | * name. Instead of using Piped streams for stream-based, inter-thread communication | ||
10 | * (where one side writes and the other reads), the code>Exchanger relies on a single | ||
11 | * exchange method for the transfer of one-off data between threads. The Exchanger is | ||
12 | * not a general replacement for the piped model, but their usages are similar. | ||
13 | * | ||
14 | * To exchange objects, you call the exchange method. The method transfers objects in both | ||
15 | * directions, not just one. | ||
16 | * | ||
17 | * An Exchanger is often used when you have two threads, one consuming a resource, | ||
18 | * and the other producing it. When the buffer used by the producer is full, the | ||
19 | * producer waits for the consumer. When the buffer used by the consumer is empty, | ||
20 | * the consumer waits for the producer. After both waits happen, the two threads swap | ||
21 | * buffers. This works well when you know more items will be produced. Otherwise, | ||
22 | * items will sit waiting for a full buffer before swapping buffers. | ||
23 | * | ||
24 | * Here's an example that uses the Exchanger. The FillingLoop class is the producer | ||
25 | * type. The EmptyingLoop class is the consumer. When the producer's data structure | ||
26 | * is full, it tries to exchange with the consumer. When the consumer's data structure | ||
27 | * is empty, it tries to exchange data structures with the producer. After both the | ||
28 | * producer and consumer are waiting, the exchange happens. | ||
29 | */ | ||
30 | |||
31 | public class ExchangerTest { | ||
32 | |||
33 | private static final int FULL = 10; | ||
34 | private static final int COUNT = FULL * 20; | ||
35 | private static final Random random = new Random(); | ||
36 | private static volatile int sum = 0; | ||
37 | |||
38 | private static Exchanger<List<Integer>> exchanger = | ||
39 | new Exchanger<List<Integer>>(); | ||
40 | |||
41 | private static List<Integer> initiallyEmptyBuffer; | ||
42 | private static List<Integer> initiallyFullBuffer; | ||
43 | private static CountDownLatch stopLatch = | ||
44 | new CountDownLatch(2); | ||
45 | |||
46 | private static class FillingLoop implements Runnable { | ||
47 | public void run() { | ||
48 | List<Integer> currentBuffer = initiallyEmptyBuffer; | ||
49 | try { | ||
50 | for (int i = 0; i < COUNT; i++) { | ||
51 | if (currentBuffer == null) | ||
52 | break; // stop on null | ||
53 | Integer item = random.nextInt(100); | ||
54 | System.out.println("Added: " + item); | ||
55 | currentBuffer.add(item); | ||
56 | if (currentBuffer.size() == FULL) | ||
57 | currentBuffer = | ||
58 | exchanger.exchange(currentBuffer); | ||
59 | } | ||
60 | } catch (InterruptedException ex) { | ||
61 | System.out.println("Bad exchange on filling side"); | ||
62 | } | ||
63 | stopLatch.countDown(); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | private static class EmptyingLoop implements Runnable { | ||
68 | public void run() { | ||
69 | List<Integer> currentBuffer = initiallyFullBuffer; | ||
70 | try { | ||
71 | for (int i = 0; i < COUNT; i++) { | ||
72 | if (currentBuffer == null) | ||
73 | break; // stop on null | ||
74 | Integer item = currentBuffer.remove(0); | ||
75 | System.out.println("Got: " + item); | ||
76 | sum += item.intValue(); | ||
77 | if (currentBuffer.isEmpty()) { | ||
78 | currentBuffer = | ||
79 | exchanger.exchange(currentBuffer); | ||
80 | } | ||
81 | } | ||
82 | } catch (InterruptedException ex) { | ||
83 | System.out.println("Bad exchange on emptying side"); | ||
84 | } | ||
85 | stopLatch.countDown(); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | public static void main(String args[]) { | ||
90 | |||
91 | initiallyEmptyBuffer = new ArrayList<Integer>(); | ||
92 | initiallyFullBuffer = new ArrayList<Integer>(FULL); | ||
93 | |||
94 | for (int i=0; i<FULL; i++) { | ||
95 | initiallyFullBuffer.add(random.nextInt(100)); | ||
96 | } | ||
97 | |||
98 | new Thread(new FillingLoop()).start(); | ||
99 | new Thread(new EmptyingLoop()).start(); | ||
100 | |||
101 | try { | ||
102 | stopLatch.await(); | ||
103 | } catch (InterruptedException ex) { | ||
104 | ex.printStackTrace(); | ||
105 | } | ||
106 | |||
107 | System.out.println("Sum of all items is.... " + sum); | ||
108 | } | ||
109 | } |