java 多线程的一个例证二

java 多线程的一个例子二

前文实现的是通过一个主进程进行轮训的方式,这篇文章是采用的是线程自己控制依赖他的线程的新、运行方式。废话不说,贴上代码

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();
    }