|
| 1 | +packagenet.sf.j2s.ajax; |
| 2 | + |
| 3 | +importjava.lang.reflect.Field; |
| 4 | +importjava.util.concurrent.ConcurrentHashMap; |
| 5 | +importjava.util.concurrent.RejectedExecutionHandler; |
| 6 | +importjava.util.concurrent.ThreadFactory; |
| 7 | +importjava.util.concurrent.TimeUnit; |
| 8 | +importjava.util.concurrent.locks.*; |
| 9 | +importjava.util.concurrent.*; |
| 10 | +importjava.util.*; |
| 11 | + |
| 12 | +publicclassChainedThreadPoolExecutorextendsSimpleThreadPoolExecutor { |
| 13 | + |
| 14 | +privateReentrantLockinternalMainLock =null; |
| 15 | + |
| 16 | +privateSet<Runnable>internalWorkers =null; |
| 17 | + |
| 18 | +privateFieldfieldWorkerThread =null; |
| 19 | + |
| 20 | +privateFieldfieldWorkerFirstTask =null; |
| 21 | + |
| 22 | +privateMap<Runnable,ChainedRunnable>runningTasks =newConcurrentHashMap<Runnable,ChainedRunnable>(); |
| 23 | + |
| 24 | +privateMap<Object,ChainedRunnable>lastTasks =newConcurrentHashMap<Object,ChainedRunnable>(); |
| 25 | + |
| 26 | +@SuppressWarnings("unchecked") |
| 27 | +privatevoidfetchInternalFields() { |
| 28 | +try { |
| 29 | +FieldfieldWorkers =ThreadPoolExecutor.class.getDeclaredField("workers"); |
| 30 | +if (fieldWorkers !=null) { |
| 31 | +fieldWorkers.setAccessible(true); |
| 32 | +Objectvalue =fieldWorkers.get(this); |
| 33 | +if (valueinstanceofSet) { |
| 34 | +internalWorkers = (Set<Runnable>)value; |
| 35 | +} |
| 36 | +} |
| 37 | +FieldfieldMainLock =ThreadPoolExecutor.class.getDeclaredField("mainLock"); |
| 38 | +if (fieldMainLock !=null) { |
| 39 | +fieldMainLock.setAccessible(true); |
| 40 | +Objectvalue =fieldMainLock.get(this); |
| 41 | +if (valueinstanceofReentrantLock) { |
| 42 | +internalMainLock = (ReentrantLock)value; |
| 43 | +} |
| 44 | +} |
| 45 | +}catch (SecurityExceptione) { |
| 46 | +e.printStackTrace(); |
| 47 | +}catch (IllegalArgumentExceptione) { |
| 48 | +e.printStackTrace(); |
| 49 | +}catch (NoSuchFieldExceptione) { |
| 50 | +e.printStackTrace(); |
| 51 | +}catch (IllegalAccessExceptione) { |
| 52 | +e.printStackTrace(); |
| 53 | +} |
| 54 | +} |
| 55 | + |
| 56 | +publicChainedThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,intidlePoolSize,longkeepAliveTime, |
| 57 | +TimeUnitunit,intqueueSize,RejectedExecutionHandlerhandler) { |
| 58 | +super(corePoolSize,maximumPoolSize,idlePoolSize,keepAliveTime,unit,queueSize,handler); |
| 59 | +fetchInternalFields(); |
| 60 | +} |
| 61 | + |
| 62 | +publicChainedThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,intidlePoolSize,longkeepAliveTime, |
| 63 | +TimeUnitunit,intqueueSize,StringpoolName) { |
| 64 | +super(corePoolSize,maximumPoolSize,idlePoolSize,keepAliveTime,unit,queueSize,poolName); |
| 65 | +fetchInternalFields(); |
| 66 | +} |
| 67 | + |
| 68 | +publicChainedThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,intidlePoolSize,longkeepAliveTime, |
| 69 | +TimeUnitunit,intqueueSize,ThreadFactorythreadFactory,RejectedExecutionHandlerhandler) { |
| 70 | +super(corePoolSize,maximumPoolSize,idlePoolSize,keepAliveTime,unit,queueSize,threadFactory,handler); |
| 71 | +fetchInternalFields(); |
| 72 | +} |
| 73 | + |
| 74 | +publicChainedThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,intidlePoolSize,longkeepAliveTime, |
| 75 | +TimeUnitunit,intqueueSize,ThreadFactorythreadFactory) { |
| 76 | +super(corePoolSize,maximumPoolSize,idlePoolSize,keepAliveTime,unit,queueSize,threadFactory); |
| 77 | +fetchInternalFields(); |
| 78 | +} |
| 79 | + |
| 80 | +publicChainedThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,intidlePoolSize,longkeepAliveTime, |
| 81 | +TimeUnitunit,intqueueSize) { |
| 82 | +super(corePoolSize,maximumPoolSize,idlePoolSize,keepAliveTime,unit,queueSize); |
| 83 | +fetchInternalFields(); |
| 84 | +} |
| 85 | + |
| 86 | + |
| 87 | +privatebooleanaddIfInQueue(ChainedRunnabletask) { |
| 88 | +Objectowner =task.getOwner(); |
| 89 | +finalReentrantLockmainLock =this.internalMainLock; |
| 90 | +mainLock.lock(); |
| 91 | +try { |
| 92 | +//System.out.println("Worker size = " + internalWorkers.size()); |
| 93 | +for (Iterator<Runnable>itr =internalWorkers.iterator();itr.hasNext();) { |
| 94 | +Runnableworker = (Runnable)itr.next(); |
| 95 | +ChainedRunnablerunningTask =runningTasks.get(worker); |
| 96 | +if (runningTask !=null &&runningTask.getOwner() ==owner) { |
| 97 | +//System.out.println("Appending task " + task + " to running task " + runningTask + " on worker " + worker); |
| 98 | +runningTask.addNext(task); |
| 99 | +lastTasks.put(owner,task); |
| 100 | +returntrue; |
| 101 | +} |
| 102 | +ChainedRunnablefirstTask =null;// worker.firstTask; |
| 103 | +try { |
| 104 | +if (fieldWorkerFirstTask ==null) { |
| 105 | +Fieldf =worker.getClass().getDeclaredField("firstTask"); |
| 106 | +if (f !=null) { |
| 107 | +f.setAccessible(true); |
| 108 | +} |
| 109 | +fieldWorkerFirstTask =f; |
| 110 | +} |
| 111 | +if (fieldWorkerFirstTask !=null) { |
| 112 | +Objectvalue =fieldWorkerFirstTask.get(worker); |
| 113 | +if (valueinstanceofChainedRunnable) { |
| 114 | +firstTask = (ChainedRunnable)value; |
| 115 | +} |
| 116 | +//System.out.println("Checking firstTask " + value + " for worker " + worker); |
| 117 | +} |
| 118 | +}catch (SecurityExceptione) { |
| 119 | +e.printStackTrace(); |
| 120 | +}catch (IllegalArgumentExceptione) { |
| 121 | +e.printStackTrace(); |
| 122 | +}catch (NoSuchFieldExceptione) { |
| 123 | +e.printStackTrace(); |
| 124 | +}catch (IllegalAccessExceptione) { |
| 125 | +e.printStackTrace(); |
| 126 | +} |
| 127 | +if (firstTask !=null &&firstTask.getOwner() ==owner) { |
| 128 | +//System.out.println("Appending task " + task + " to first task " + runningTask + " on worker " + worker); |
| 129 | +firstTask.addNext(task); |
| 130 | +lastTasks.put(owner,task); |
| 131 | +returntrue; |
| 132 | +} |
| 133 | +} |
| 134 | +for (Iterator<Runnable>itr =getQueue().iterator();itr.hasNext();) { |
| 135 | +Runnablenext =itr.next(); |
| 136 | +if (nextinstanceofChainedRunnable) { |
| 137 | +ChainedRunnabler = (ChainedRunnable)next; |
| 138 | +if (r.getOwner() ==owner) { |
| 139 | +//System.out.println("Appending task " + task + " to queued task " + r); |
| 140 | +r.addNext(task); |
| 141 | +lastTasks.put(owner,task); |
| 142 | +returntrue; |
| 143 | +} |
| 144 | +} |
| 145 | +} |
| 146 | +ChainedRunnablelast =lastTasks.get(owner); |
| 147 | +if (last !=null && !last.isDone()) { |
| 148 | +//System.out.println("Appending task " + task + " to last task " + last); |
| 149 | +last.addNext(task); |
| 150 | +lastTasks.put(owner,task); |
| 151 | +returntrue; |
| 152 | + } |
| 153 | + |
| 154 | +//System.out.println("Not in queue, starting new worker for " + task); |
| 155 | +lastTasks.put(owner,task); |
| 156 | +returnfalse; |
| 157 | + }finally { |
| 158 | +mainLock.unlock(); |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | +publicvoidexecute(Objectowner,Runnablecommand) { |
| 163 | +ChainedRunnabletask =newChainedRunnable(owner,command); |
| 164 | +execute(task); |
| 165 | + } |
| 166 | + |
| 167 | +@Override |
| 168 | +publicvoidexecute(Runnablecommand) { |
| 169 | +if (command ==null) |
| 170 | +thrownewNullPointerException(); |
| 171 | +if (!(commandinstanceofChainedRunnable)) { |
| 172 | +thrownewRuntimeException("Not a chained runnable task"); |
| 173 | + } |
| 174 | +ChainedRunnablechainCommand = (ChainedRunnable)command; |
| 175 | +if (addIfInQueue(chainCommand)) { |
| 176 | +return; |
| 177 | + } |
| 178 | +super.execute(command); |
| 179 | +} |
| 180 | + |
| 181 | +@Override |
| 182 | +protectedvoidafterExecute(Runnabler,Throwablet) { |
| 183 | +finalReentrantLockmainLock =this.internalMainLock; |
| 184 | +booleanremoveError =false; |
| 185 | +mainLock.lock(); |
| 186 | +try { |
| 187 | +for (Map.Entry<Runnable,ChainedRunnable>entry :runningTasks.entrySet()) { |
| 188 | +if (entry.getValue() ==r) { |
| 189 | +runningTasks.remove(entry.getKey()); |
| 190 | +break; |
| 191 | + } |
| 192 | + } |
| 193 | +if (rinstanceofChainedRunnable) { |
| 194 | +ChainedRunnabletask = (ChainedRunnable)r; |
| 195 | +Objectowner =task.getOwner(); |
| 196 | +ChainedRunnablelastTask =lastTasks.get(owner); |
| 197 | +if (lastTask ==task) { |
| 198 | +ChainedRunnablelast =lastTasks.remove(owner); |
| 199 | +removeError =last !=task; |
| 200 | + } |
| 201 | + } |
| 202 | + }finally { |
| 203 | +mainLock.unlock(); |
| 204 | + } |
| 205 | +if (removeError) { |
| 206 | +System.out.println("Removed updated last task " +r); |
| 207 | +} |
| 208 | +super.afterExecute(r,t); |
| 209 | +} |
| 210 | + |
| 211 | +@Override |
| 212 | +protectedvoidbeforeExecute(Threadt,Runnabler) { |
| 213 | +finalReentrantLockmainLock =this.internalMainLock; |
| 214 | +mainLock.lock(); |
| 215 | +try { |
| 216 | +for (Runnableworker :internalWorkers) { |
| 217 | +try { |
| 218 | +if (fieldWorkerThread ==null) { |
| 219 | +Fieldf =worker.getClass().getDeclaredField("thread"); |
| 220 | +if (f !=null) { |
| 221 | +f.setAccessible(true); |
| 222 | + } |
| 223 | +fieldWorkerThread =f; |
| 224 | + } |
| 225 | +if (fieldWorkerThread !=null) { |
| 226 | +Objectvalue =fieldWorkerThread.get(worker); |
| 227 | +if (t ==value) { |
| 228 | +if (rinstanceofChainedRunnable) { |
| 229 | +runningTasks.put(worker, (ChainedRunnable)r); |
| 230 | +break; |
| 231 | + }// else dummy task |
| 232 | + } |
| 233 | + } |
| 234 | + }catch (SecurityExceptione) { |
| 235 | +e.printStackTrace(); |
| 236 | + }catch (IllegalArgumentExceptione) { |
| 237 | +e.printStackTrace(); |
| 238 | + }catch (NoSuchFieldExceptione) { |
| 239 | +e.printStackTrace(); |
| 240 | + }catch (IllegalAccessExceptione) { |
| 241 | +e.printStackTrace(); |
| 242 | + } |
| 243 | + } |
| 244 | + }finally { |
| 245 | +mainLock.unlock(); |
| 246 | + } |
| 247 | +super.beforeExecute(t,r); |
| 248 | +} |
| 249 | + |
| 250 | +} |