1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sourceforge.domian.test.benchmark;
17
18
19 import java.text.SimpleDateFormat;
20 import java.util.Date;
21 import java.util.Iterator;
22
23 import net.sourceforge.domian.repository.PartitionRepository;
24 import net.sourceforge.domian.repository.PersistentRepository;
25 import net.sourceforge.domian.repository.Repository;
26 import net.sourceforge.domian.util.StopWatch;
27 import net.sourceforge.domian.util.concurrent.task.ConcurrentRepositoryTaskExecutor;
28 import net.sourceforge.domian.util.concurrent.task.RepositoryTask;
29
30 import static net.sourceforge.domian.specification.SpecificationFactory.all;
31 import static net.sourceforge.domian.test.benchmark.QueenPuzzleUtils.conditionalLogging;
32 import static org.apache.commons.lang.math.RandomUtils.nextInt;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 class ConcurrentQueenPuzzle extends AbstractQueenPuzzle {
52
53 ConcurrentQueenPuzzle(final SequentialQueenPuzzle.RepositoryType repositoryType,
54 final long numberOfConstellations,
55 final int numberOfWorkers,
56 final long logInterval) {
57 super(repositoryType, numberOfConstellations, numberOfWorkers, logInterval);
58 }
59
60
61 void solvePuzzle() {
62 System.out.println();
63 System.out.println("Solving the \"Queen Puzzle\" concurrently... [start time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS").format(new Date()) + "]");
64 System.out.println("Processors : " + Runtime.getRuntime().availableProcessors());
65 System.out.println("Worker threads : " + this.numberOfWorkers);
66 System.out.println("Constellations : " + this.numberOfConstellations + " + 1 correct one for completion control");
67 System.out.println("Repository type : " + this.repositoryType);
68 System.out.println();
69
70
71 final Repository<QueenPuzzleConstellation> repo = createRepository(this.repositoryType);
72 if (repo instanceof PersistentRepository) {
73 PersistentRepository persistentRepository = (PersistentRepository) repo;
74 repo.remove(all(QueenPuzzleConstellation.class));
75 if (persistentRepository.getPersistenceDefinition().supportsAsynchronousPersistence()) {
76 persistentRepository.persist();
77 }
78 }
79
80 final StopWatch stopWatch = new StopWatch().start();
81
82
83 if (repo instanceof PartitionRepository) {
84
85 ((PartitionRepository<QueenPuzzleConstellation>) repo).addPartitionFor(queenPuzzleConstellationsThatIsProcessedAndMarkedAsToSolveTheQueenPuzzle, "approved-queenpuzzle-constellations");
86 ((PartitionRepository<QueenPuzzleConstellation>) repo).addPartitionFor(unProcessedQueenPuzzleConstellations, "unprocessed-queenpuzzle-constellations");
87 }
88
89
90 addOneWellKnownSuccessfulQueenPuzzleConstellationInto(repo);
91
92
93 final ConcurrentRepositoryTaskExecutor concurrentTaskExecutor = new ConcurrentRepositoryTaskExecutor(repo);
94 for (int producerNumber = 0; producerNumber < this.numberOfWorkers; ++producerNumber) {
95 concurrentTaskExecutor.addTask(new RandomPermutationQueenPuzzleConstellationProducer(this.numberOfConstellations / this.numberOfWorkers,
96 this.logInterval));
97 }
98 System.out.println("Starting concurrent execution of " + this.numberOfWorkers + " worker threads...");
99 try {
100 concurrentTaskExecutor.execute();
101 } catch (Exception e) {
102 e.printStackTrace();
103 throw new RuntimeException(e);
104 }
105 System.out.println("Concurrent execution of worker threads terminated!");
106
107 doPrintProcessStatistics(stopWatch.getElapsedTime(), this.numberOfConstellations);
108
109
110
111
112
113
114
115
116 if (repo instanceof PersistentRepository) {
117 doPersist((PersistentRepository) repo);
118 }
119
120
121 doResultSearch(repo);
122
123
124 doCompletionControl(repo);
125
126 System.out.println();
127 System.out.println("Overall time: " + stopWatch);
128 }
129
130
131 private static class RandomPermutationQueenPuzzleConstellationProducer extends RepositoryTask<Repository<QueenPuzzleConstellation>> {
132
133 final long numberOfConstellationsToProduce;
134 final long logInterval;
135
136 RandomPermutationQueenPuzzleConstellationProducer(final long numberOfConstellationsToProduce, final long logInterval) {
137 super();
138 this.numberOfConstellationsToProduce = numberOfConstellationsToProduce;
139 this.logInterval = logInterval;
140 }
141
142
143 private boolean constellationConstraintOk(final int[] queenPlacingNumbers, final int queenPlacingIndex, final int queenPlacingNumber) {
144 for (int index = 0; index < queenPlacingIndex; ++index) {
145 if (queenPlacingNumber == queenPlacingNumbers[index]) {
146 return false;
147 }
148 }
149 return true;
150 }
151
152 public void doConcurrentTask() {
153 long processingCounter = 0;
154 long redundantProcessingCounter = 0;
155
156 final StopWatch stopWatch = new StopWatch().start();
157
158
159 for (long workerInternalConstellationNumber = 1;
160 workerInternalConstellationNumber <= this.numberOfConstellationsToProduce;
161 ++workerInternalConstellationNumber) {
162 final int[] constellation = new int[8];
163 int index = 0;
164 while (index < 8) {
165 int number = nextInt(64);
166 while (!constellationConstraintOk(constellation, index, number)) {
167 number = nextInt(64);
168 }
169 constellation[index++] = number;
170 }
171 final QueenPuzzleConstellation queenPuzzleConstellation = new QueenPuzzleConstellation(new ChessPiecePlacing(constellation[0]),
172 new ChessPiecePlacing(constellation[1]),
173 new ChessPiecePlacing(constellation[2]),
174 new ChessPiecePlacing(constellation[3]),
175 new ChessPiecePlacing(constellation[4]),
176 new ChessPiecePlacing(constellation[5]),
177 new ChessPiecePlacing(constellation[6]),
178 new ChessPiecePlacing(constellation[7]));
179 this.repository.put(queenPuzzleConstellation);
180 conditionalLogging((long) this.threadNumber, this.logInterval, workerInternalConstellationNumber, stopWatch, queenPuzzleConstellation, "generated and added to repo so far...");
181 }
182
183
184 final Iterator<? extends QueenPuzzleConstellation> allUnprocessedConstellations = this.repository.iterateAll(unProcessedQueenPuzzleConstellations);
185 long numberOfProcessedConstellations = 0;
186 while (allUnprocessedConstellations.hasNext()) {
187 QueenPuzzleConstellation unProcessedQueenPuzzleConstellation = allUnprocessedConstellations.next();
188
189
190 synchronized (unProcessedQueenPuzzleConstellation) {
191 if (unProcessedQueenPuzzleConstellation.isProcessed()) {
192 ++redundantProcessingCounter;
193 } else {
194 unProcessedQueenPuzzleConstellation.setSolvesQueenPuzzle(queenPuzzleConstellationsThatInherentlySolvesTheQueenPuzzle.isSatisfiedBy(unProcessedQueenPuzzleConstellation));
195 this.repository.update(unProcessedQueenPuzzleConstellation);
196 ++processingCounter;
197 }
198 conditionalLogging((long) this.threadNumber, logInterval, ++numberOfProcessedConstellations, stopWatch, unProcessedQueenPuzzleConstellation, "processed so far...");
199 }
200
201
202
203
204 }
205
206 System.out.println("Worker thread #" + this.threadNumber + " finished. " + processingCounter + " puzzle constellation processed by this worker. " + redundantProcessingCounter + " puzzle constellation was already processed.");
207
208 }
209 }
210 }