001 /*
002 * Java Genetic Algorithm Library (jenetics-1.6.0).
003 * Copyright (c) 2007-2014 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.util;
021
022 import java.util.Properties;
023 import java.util.concurrent.ForkJoinPool;
024
025 import javolution.context.ConcurrentContext;
026 import javolution.context.Context;
027 import javolution.context.LogContext;
028 import javolution.lang.Configurable;
029
030 /**
031 * Simplify the usage of the {@link ConcurrentContext} usage by using the the
032 * Java 'try' for resources capability.
033 * <p/>
034 * Normally you will write
035 * [code]
036 * ConcurrentContext.enter();
037 * try {
038 * ConcurrentContext.execute(task1);
039 * ConcurrentContext.execute(task2); }
040 * } finally {
041 * ConcurrentContext.exit();
042 * }
043 * [/code]
044 * to execute two tasks. By using this class you can shorten the code to be
045 * written to:
046 * [code]
047 * try (Concurrency c = Concurrency.start()) {
048 * c.execute(task1);
049 * c.execute(task2);
050 * }
051 * [/code]
052 *
053 * The configuration is performed as followed, before executing any concurrent
054 * code.
055 * [code]
056 * public class Main {
057 * public static void main(final String[] args) {
058 * // Using 10 threads for evolving.
059 * Concurrency.setConcurrency(9);
060 *
061 * // Forces the application only to use one thread.
062 * Concurrency.setConcurrency(0);
063 * }
064 * }
065 * [/code]
066 *
067 * The {@code ConcurrentContext} from the <i>JScience</i> project uses it's
068 * own--optimized--thread-pool implementation. If you need to have a single
069 * executor service, for the GA and your own classes, you can initialize the
070 * {@code Concurrency} class with the {@link ForkJoinPool} from the JDK.
071 *
072 * [code]
073 * public class Main {
074 * public static void main(final String[] args) {
075 * final int nthreads = 10;
076 * final ForkJoinPool pool = new ForkJoinPool(nthreads);
077 * Concurrency.setForkJoinPool(pool);
078 * ...
079 * }
080 * }
081 * [/code]
082 *
083 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
084 * @since 1.0
085 * @version 1.0 — <em>$Date: 2013-12-18 $</em>
086 */
087 public final class Concurrency implements AutoCloseable {
088
089 private static final String KEY_CONTEXT =
090 "javolution.context.ConcurrentContext#DEFAULT";
091
092 private static final String KEY_CONCURRENTCY =
093 "javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY";
094
095 private static final Concurrency INSTANCE = new Concurrency();
096
097 private Concurrency() {
098 }
099
100 /**
101 * Set the number of threads to use by the {@link ConcurrentContext}.
102 *
103 * @param concurrency the number of threads to use for the default concurrent
104 * context.
105 */
106 public static void setConcurrency(final int concurrency) {
107 if (concurrency > ConcurrentContext.getConcurrency()) {
108 final Properties properties = new Properties();
109 properties.put(KEY_CONCURRENTCY, concurrency);
110 setProperties(properties);
111 }
112
113 ConcurrentContext.setConcurrency(concurrency);
114 }
115
116 /**
117 * Set the concurrent-context to be used by the concurrency.
118 *
119 * @param type the concurrent-context type.
120 * @throws NullPointerException if the given {@code type} is {@code null}.
121 */
122 public static void setContext(final Class<? extends ConcurrentContext> type) {
123 final Properties properties = new Properties();
124 properties.put(KEY_CONTEXT, type);
125 setProperties(properties);
126 }
127
128 /**
129 * Convenience method for setting the {@link ForkJoinPool} and the concurrent
130 * context to {@link ForkJoinContext}.
131 *
132 * @param pool the {@link ForkJoinPool} to use for concurrency.
133 */
134 public static void setForkJoinPool(final ForkJoinPool pool) {
135 ForkJoinContext.setForkJoinPool(pool);
136 setContext(ForkJoinContext.class);
137 }
138
139 private static void setProperties(final Properties properties) {
140 Context.enter(LogContext.NULL);
141 try {
142 Configurable.read(properties);
143 } finally {
144 Context.exit();
145 }
146 }
147
148 /**
149 * Reset to the default default context.
150 */
151 public static void setDefaultContext() {
152 setContext(ConcurrentContext.DEFAULT.get());
153 }
154
155 @SuppressWarnings("unchecked")
156 public static Class<ConcurrentContext> getContext() {
157 final Context context = Context.getCurrent();
158 return (Class<ConcurrentContext>)
159 ConcurrentContext.class.cast(context).getClass();
160 }
161
162 public static Concurrency start() {
163 ConcurrentContext.enter();
164 return INSTANCE;
165 }
166
167 @SuppressWarnings("static-method")
168 public void execute(final Runnable task) {
169 ConcurrentContext.execute(task);
170 }
171
172 @Override
173 public void close() {
174 ConcurrentContext.exit();
175 }
176
177 }
|