前文实现的是通过一个主进程进行轮训的方式,这篇文章是采用的是线程自己控制依赖他的线程的新、运行方式。废话不说,贴上代码
xml的解析代码没有改动。主要是贴的是Thread的代码
package com.simple2; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; public class MyThread extends Thread { private static Map<MyThread,String> session = new HashMap<MyThread,String>(); //进行lock的Session private static String[] lockSession = new String[10]; private int account; public MyThread(){ } public int getAfterCount(){ return this.account; } public void setAfterCount(int count){ this.account = count; } public void subAfterCount(){ this.account--; } public static void initStaticDomain(){ produceLockSession(); initSession(); } //初始化随机数 private static void initSession(){ List<ThreadEntity> threadlist = ThreadList.getThreadlist(); for(int i = 0;i < threadlist.size();i++){ session.put(threadlist.get(i).getProcess(), lockSession[i]); } } private static void produceLockSession(){ String source = "abcdefghijklmnopqrstuvwxyz"; String[] lockSession = MyThread.getLockSession(); Random random = new Random(); for(int i = 0;i < lockSession.length;i++){ StringBuilder builder = new StringBuilder(); //begin to generate a random string which of length is 5 for(int j = 0;j < 5;j++){ int position = random.nextInt(source.length()); builder.append(source.charAt(position)); } String temp = builder.toString(); //判断生成的string 是否重复 for(int j = 0;j < lockSession.length;j++){ String curr = lockSession[i]; if(curr == null || curr.length() == 0){ lockSession[i] = temp; }else if(curr.equals(temp)){ //有重复的再次生成; i--; break; }else{ //不重复,比较下一个 continue; } } } } public static String[] getLockSession() { return lockSession; } public static void setLockSession(String[] lockSession) { MyThread.lockSession = lockSession; } private void preProcess(){ if(this.account != 0){ String lock = session.get(this); synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } //对象进行初始化的时候进行,否则会发生死锁 public void initAccount() { List<ThreadEntity> threadlist = ThreadList.getThreadlist(); for(ThreadEntity then : threadlist){ if(then.getProcess() == this){ //设置account的值 setAfterCount(then.getPreEntities().size()); break; } } } //运行完毕之后 private void notifyAfter(){ List<ThreadEntity> threadlist = ThreadList.getThreadlist(); for(ThreadEntity te : threadlist){ //依赖currentThread 的ThreadEntity subAfterCount for(Map.Entry<Integer, ThreadEntity> entry:te.getPreEntities().entrySet()){ MyThread thread = entry.getValue().getProcess(); if(thread == this) { te.getProcess().subAfterCount(); } } //如果te代表的Thread subAfount为零,则开始将该进程的状态由wait变成run if(te.getProcess().getAfterCount() == 0) { String lock = session.get(te.getProcess()); synchronized (lock) { try { lock.notify(); } catch (Exception e) { e.printStackTrace(); } } } } } @Override public void run() { try { //保证我们的所有的线程启动的时间在别的线程完成的时间前 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } preProcess(); realRun(); notifyAfter(); } private void realRun() { List<ThreadEntity> threadlist = ThreadList.getThreadlist(); for(ThreadEntity then : threadlist){ if(then.getProcess() == this) { System.out.println("current running Thread ID :" + then.getThreadID()); } } } }
Entity的代码没有什么改变,只是参数process改为MyThread
代码如下
package com.simple2; import java.util.HashMap; import java.util.Map; import com.simple2.ThreadEntity; public class ThreadEntity { private Integer threadID; private Map<Integer,ThreadEntity> preEntities; private MyThread process; private boolean ready = false; public ThreadEntity(){ preEntities = new HashMap<Integer, ThreadEntity>(); process = new MyThread(); } public Integer getThreadID() { return threadID; } public void setThreadID(Integer threadID) { this.threadID = threadID; } public Map<Integer, ThreadEntity> getPreEntities() { return preEntities; } public void setPreEntities(Map<Integer, ThreadEntity> preEntities) { this.preEntities = preEntities; } public MyThread getProcess() { return process; } public void setProcess(MyThread process) { this.process = process; } public boolean isReady() { return ready; } public void setReady(boolean ready) { this.ready = ready; } public void addPreEntity(ThreadEntity te) { this.preEntities.put(te.getThreadID(), te); } }
由上文我们可以知道,MyThread 创建对象的时候就对static 的对象尽心初始化,会造成初始化的error,这个是因为,MyThread 依赖 Threadlist ,但是Threadlist设置threadlist的时候,正好也是依赖MyThread,我只有先对MyThread进行初始化,然后再设置threadlist。
所以说,MyThread static 里的成员,最好等threadlist初始化之后,在进行初始化。所以说,他们的生命周期需要向后推迟。还有当我们对account进行初始化的时候,不能在线程启动之后之后进行初始化。但是account又依赖于threadlist,所以说,account 也是不能在对象初始化的时候进行初始化,也是将生命周期延后。所以说,threadlist的代码如下
package com.simple2; import java.util.List; /** * 描述: * @author tippy * @date 2011-5-15 */ public class ThreadList { private static List<ThreadEntity> threadlist; public static List<ThreadEntity> getThreadlist() { return threadlist; } public static void setThreadlist(List<ThreadEntity> threadList) { threadlist = threadList; } public static void startProcess() { for(ThreadEntity then:threadlist) { then.getProcess().initAccount(); then.getProcess().start(); } } }
我用junit测试的时候,犹如,一个test运行完成之后,就认为测试完成,所以别的线程的测试结果总是无法显示,所以使用main进行测试
public static void main(String[] args) throws Throwable {
ThreadList.setThreadlist(SimpleParse2.parseSimpleXML());
MyThread.initStaticDomain();
ThreadList.startProcess();
}