论坛首页 Java企业应用论坛

线程监视器

浏览 5820 次
锁定老帖子 主题:线程监视器
精华帖 (3) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-02-19  
大家都知道线程是不可靠的,我想了一些办法去监视线程当前的运行状态,能得到比如该线程到了那个类的那个方法了,到了哪一行了,在细粒度的控制上还是有一定作用的。

之前去实现jdk里的Observer接口写了一个,但是发现 实际上还是由线程自己触发内部的event后,listener才能响应,一旦线程阻塞,没有event了,listener也没有意义了。这样始终是被动得到线程发出的信息。

想要主动的获得线程的运行信息,需要一个timer 定时去主动获取它的状态,也就是获得当前线程对象的方法堆栈。
如果发现目标线程已经结束,则关闭监视器。如果因为发生预期外的阻塞而timeout,也关闭监视器,由于已经将目标线程设置成deamon,目标线程也将结束。
这样能完全掌握目标线程的一举一动,不听话就干掉。是不是很有快感?

ThreadMonitor使用办法
ThreadMonitor thread = new ThreadMonitor(new OneThread(),5000,1000);
thread.start();


ThreadMonitor:
public class ThreadMonitor {
	private Thread thread;
	private Timer timer = new Timer();
	private long period,timeout,startTime;
	private boolean isFirst;
	
	public ThreadMonitor(Thread thread,long timeout,long period){
		this.thread = thread;
		init(timeout, period);
	}
	
	public ThreadMonitor(Runnable runnable,long timeout,long period){
		thread = new Thread(runnable);
		init(timeout, period);
	}
	
	private void init(long timeout,long period){
		isFirst = true;
		this.period = period;
		this.timeout = timeout;
		startTime = System.currentTimeMillis();
	}
	
	public void start(){
		timer.schedule(new TimerTask(){
			public void run() {
				if(isFirst)
					thread.setDaemon(true);
				boolean isTimeout = System.currentTimeMillis() - startTime>timeout;
				if(!isFirst && (isTimeout || !thread.isAlive())){
					timer.cancel();
					if(!isTimeout && !thread.isAlive())
						System.out.println("Thread is over");
					if(isTimeout)
						System.out.println("Timeout");
					if(!thread.isAlive())
						System.out.println("Close target thread");
					System.out.println("Close thread monitor");
				}else {
					long now = System.currentTimeMillis();
					StackTraceElement elements[] = thread.getStackTrace();
					if(elements.length >0)
						for(StackTraceElement element : elements){
							System.out.println("["+(now-startTime)+"] Current: "+ element.getClassName()+" " +element.getMethodName()+"() line:"+element.getLineNumber());
						}
					else
						System.out.println("Stack is null");
				}
				isFirst = false;
			}
		}, 0, period);
		thread.start();
	}
}


下面是例子
OneThread:
public class OneThread implements Runnable {
	public void run() {
		ThreadUtil util = new ThreadUtil();
		util.step1();
		util.step2();
		util.step3();
	}
}


ThreadUtil:
public class ThreadUtil {
	public void step1(){
		synchronized(this){
			try {
				wait(1000);
			} catch (InterruptedException e) {
				System.out.println("1:"+e.getMessage());
			}
		}
	System.out.println("step1 finished");
	}
	public void step2(){
		synchronized(this){
			try {
				wait(3000);
			} catch (InterruptedException e) {
				System.out.println("3:"+e.getMessage());
			}
		}
	System.out.println("step3 finished");
	}
	public void step3(){
		synchronized(this){
			try {
				wait(2000);
			} catch (InterruptedException e) {
				System.out.println("3:"+e.getMessage());
			}
		}
	System.out.println("step3 finished");
	}
}


下面是输出:
Stack is null
[1002] Current: java.lang.Object wait() line:-2
[1002] Current: org.jomper.test.thread.ThreadUtil step1() line:7
[1002] Current: org.jomper.test.thread.OneThread run() line:7
[1002] Current: java.lang.Thread run() line:595
step1 finished
[2006] Current: java.lang.Object wait() line:-2
[2006] Current: org.jomper.test.thread.ThreadUtil step2() line:17
[2006] Current: org.jomper.test.thread.OneThread run() line:8
[2006] Current: java.lang.Thread run() line:595
[3010] Current: java.lang.Object wait() line:-2
[3010] Current: org.jomper.test.thread.ThreadUtil step2() line:17
[3010] Current: org.jomper.test.thread.OneThread run() line:8
[3010] Current: java.lang.Thread run() line:595
step2 finished
[4010] Current: java.lang.Object wait() line:-2
[4010] Current: org.jomper.test.thread.ThreadUtil step3() line:27
[4010] Current: org.jomper.test.thread.OneThread run() line:9
[4010] Current: java.lang.Thread run() line:595
Timeout
Close thread monitor


大家来讨论把,还有没有更好的办法,或者思路上有没有问题,有没有想错的地方。
   发表时间:2008-02-20  
我犯了一个错误,之前把thread.setDaemon(true);  方到TimeTask之外了.成了主线程不消亡target thread就不消亡,我并没有干掉target thread!

现在我把他放到TimeTask里,从输出里可以看到,target thread的确是已经终止了。System.out.println("step3 finished");  并没有输出。

现在有一种办法是在 target thread 内部设置 标志位,然后double check.来终止线程内部流程而使 target thread 终止。
public void run(){
    while(!isInterrupted){
    //todo process
    }
}
这样安全,但是这样就有入侵.

把target thread 设置成守护线程,通过主线程的可控性终止来间接实现 target thread的终止,这是不是也是一种思路呢?
0 请登录后投票
   发表时间:2009-01-19  
通过thread.isAlive()获取线程状态依然存在同步问题
0 请登录后投票
   发表时间:2009-01-19  
threadDump?
0 请登录后投票
   发表时间:2009-01-19  
谁说线程不可靠?自己做POOL还是有不少要求而已。异常的处理非常重要, 如果一直扔出去, 那么线程自然就自动退出了。 实际上, 即使监控到线程被LOCK,或者挂住, 监控也是无能为力的。因此还是需要仔细设计好为上策。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics