protected AddressSetView runParallelAddressAnalysis(final Program program, final Set<Address> locations, final AddressSetView restrictedSet, int maxThreads,
			final TaskMonitor monitor) throws CancelledException, InterruptedException, Exception {
			
				monitor.checkCancelled();
			
				final AddressSet analyzedSet = new AddressSet();
				if (locations.isEmpty()) {
					return analyzedSet;
				}
			
				GThreadPool pool = AutoAnalysisManager.getSharedAnalsysThreadPool();
				monitor.setMaximum(locations.size());
			
				QCallback<Address, AddressSetView> callback = new QCallback<Address, AddressSetView>() {
					@Override
					public AddressSetView process(Address loc, TaskMonitor taskMonitor) {
						synchronized (analyzedSet) {
							if (analyzedSet.contains(loc)) {
								taskMonitor.incrementProgress(1);
								return EMPTY_ADDRESS_SET;
							}
						}
			
						try {
							AddressSetView result = analyzeLocation(program, loc, restrictedSet, taskMonitor);
							synchronized (analyzedSet) {
								analyzedSet.add(result);
							}
			
							taskMonitor.incrementProgress(1);
							return result;
						}
						catch (CancelledException e) {
							return null; // monitor was cancelled
						}
					}
				};
				
				// bound check thread limit	
				if (maxThreads > pool.getMaxThreadCount()) {
					maxThreads = pool.getMaxThreadCount();
				}
				if (maxThreads < 1) {
					maxThreads = 1;
				}
				
				// @formatter:off
				ConcurrentQ<Address, AddressSetView> queue = new ConcurrentQBuilder<Address, AddressSetView>()
					.setThreadPool(pool)
					.setMaxInProgress(maxThreads)
					.setMonitor(monitor)
					.build(callback);
				// @formatter:on
			
				queue.add(locations);
			
				queue.waitUntilDone();
			
				return analyzedSet;
			}
Run constant an analysis at each location in parallel

@param program program
@param locations points to analyze
@param restrictedSet set to restrict analysis to, null if none
@param maxThreads maximum number of threads to use
@param monitor to cancel
@return set of addresses covered during analysis

@throws CancelledException if cancelled
@throws InterruptedException if interrupted
@throws Exception any exception
Ghidra/Features/Base/src/main/java/ghidra/app/services/AbstractAnalyzer.java