84 * Worker, meaning that it can be reset and restarted. Due to this, a Service 85 * can be constructed declaratively and restarted on demand. 86 * Once a Service is started, it will schedule its Task and listen for 87 * changes to the state of the Task. A Task does not hold a reference to the 88 * Service that started it, meaning that a running Task will not prevent 89 * the Service from being garbage collected. 90 * </p> 91 * <p> 92 * If an {@link java.util.concurrent.Executor} is specified on the Service, 93 * then it will be used to actually execute the service. Otherwise, 94 * a daemon thread will be created and executed. If you wish to create 95 * non-daemon threads, then specify a custom Executor (for example, 96 * you could use a {@link ThreadPoolExecutor} with a custom 97 * {@link java.util.concurrent.ThreadFactory}). 98 * </p> 99 * <p> 100 * Because a Service is intended to simplify declarative use cases, subclasses 101 * should expose as properties the input parameters to the work to be done. 102 * For example, suppose I wanted to write a Service which read the first line 103 * from any URL and returned it as a String. Such a Service might be defined, 104 * such that it had a single property, <code>url</code>. It might be implemented 105 * as: 106 * <pre><code> 107 * public static class FirstLineService extends Service<String> { 108 * private StringProperty url = new SimpleStringProperty(this, "url"); 109 * public final void setUrl(String value) { url.set(value); } 110 * public final String getUrl() { return url.get(); } 111 * public final StringProperty urlProperty() { return url; } 112 * 113 * protected Task createTask() { 114 * final String _url = getUrl(); 115 * return new Task<String>() { 116 * protected String call() throws Exception { 117 * URL u = new URL(_url); 118 * BufferedReader in = new BufferedReader( 119 * new InputStreamReader(u.openStream())); 120 * String result = in.readLine(); 121 * in.close(); 122 * return result; 123 * } 124 * }; 125 * } 126 * } 127 * </code></pre> 128 * </p> 129 * <p> 130 * The Service by default uses a thread pool Executor with some unspecified 131 * default or maximum thread pool size. This is done so that naive code 132 * will not completely swamp the system by creating thousands of Threads. 133 * </p> 134 * @param <V> 135 * @since JavaFX 2.0 136 */ 137 public abstract class Service<V> implements Worker<V>, EventTarget { 138 /** 139 * Logger used in the case of some uncaught exceptions 140 */ 141 private static final PlatformLogger LOG = PlatformLogger.getLogger(Service.class.getName()); 142 143 /* 144 The follow chunk of static state is for defining the default Executor used 145 with the Service. This is based on pre-existing JavaFX Script code and 146 experience with JavaFX Script. It was necessary to have a thread pool by default 147 because we found naive code could totally overwhelm the system otherwise 148 by spawning thousands of threads for fetching resources, for example. 149 We also set the priority and daemon status of the thread in its thread 150 factory. 151 */ 152 private static final int THREAD_POOL_SIZE = 32; 153 private static final long THREAD_TIME_OUT = 1000; 154 | 84 * Worker, meaning that it can be reset and restarted. Due to this, a Service 85 * can be constructed declaratively and restarted on demand. 86 * Once a Service is started, it will schedule its Task and listen for 87 * changes to the state of the Task. A Task does not hold a reference to the 88 * Service that started it, meaning that a running Task will not prevent 89 * the Service from being garbage collected. 90 * </p> 91 * <p> 92 * If an {@link java.util.concurrent.Executor} is specified on the Service, 93 * then it will be used to actually execute the service. Otherwise, 94 * a daemon thread will be created and executed. If you wish to create 95 * non-daemon threads, then specify a custom Executor (for example, 96 * you could use a {@link ThreadPoolExecutor} with a custom 97 * {@link java.util.concurrent.ThreadFactory}). 98 * </p> 99 * <p> 100 * Because a Service is intended to simplify declarative use cases, subclasses 101 * should expose as properties the input parameters to the work to be done. 102 * For example, suppose I wanted to write a Service which read the first line 103 * from any URL and returned it as a String. Such a Service might be defined, 104 * such that it had a single property, {@code url}. It might be implemented 105 * as: 106 * </p> 107 * <pre><code> 108 * public static class FirstLineService extends Service<String> { 109 * private StringProperty url = new SimpleStringProperty(this, "url"); 110 * public final void setUrl(String value) { url.set(value); } 111 * public final String getUrl() { return url.get(); } 112 * public final StringProperty urlProperty() { return url; } 113 * 114 * protected Task createTask() { 115 * final String _url = getUrl(); 116 * return new Task<String>() { 117 * protected String call() throws Exception { 118 * URL u = new URL(_url); 119 * BufferedReader in = new BufferedReader( 120 * new InputStreamReader(u.openStream())); 121 * String result = in.readLine(); 122 * in.close(); 123 * return result; 124 * } 125 * }; 126 * } 127 * } 128 * </code></pre> 129 * <p> 130 * The Service by default uses a thread pool Executor with some unspecified 131 * default or maximum thread pool size. This is done so that naive code 132 * will not completely swamp the system by creating thousands of Threads. 133 * </p> 134 * @param <V> the type of object returned by the Service. 135 * @since JavaFX 2.0 136 */ 137 public abstract class Service<V> implements Worker<V>, EventTarget { 138 /** 139 * Logger used in the case of some uncaught exceptions 140 */ 141 private static final PlatformLogger LOG = PlatformLogger.getLogger(Service.class.getName()); 142 143 /* 144 The follow chunk of static state is for defining the default Executor used 145 with the Service. This is based on pre-existing JavaFX Script code and 146 experience with JavaFX Script. It was necessary to have a thread pool by default 147 because we found naive code could totally overwhelm the system otherwise 148 by spawning thousands of threads for fetching resources, for example. 149 We also set the priority and daemon status of the thread in its thread 150 factory. 151 */ 152 private static final int THREAD_POOL_SIZE = 32; 153 private static final long THREAD_TIME_OUT = 1000; 154 |