java线程处理问题

baihuihui 2010-02-23 06:34:54
     
public class Outdb extends Thread implements SignalHandler {
........................
........................

private void signalCallback(Signal sn) {
System.out.println(sn.getName() + "is recevied.");
System.out.println("-----------------------------");
System.out.println("SINGAL:" + Thread.activeCount());
System.exit(0);
}

public void run() {
System.out.println("-----------------------------");
System.out.println("addShutdownHook run:" + Thread.activeCount());
appExit();
}

/**
* @重写信号处理函数
* @说明:当接收信号时调用调用信号处理函数
* @Date : 2010-02-01
* @param: 注册信号名称
*/
public void handle(Signal signalName) {
signalCallback(signalName);
// Chain back to previous handler, if one exists
if (oldHandler != SIG_DFL && oldHandler != SIG_IGN) {
System.out.println("another signal received , Chain back!");
oldHandler.handle(signalName);
}

}

/**
* @Main 主函数
* @Date : 2010-02-01
* @param: param 程序调用参数数组
*/
public static void main(String param[]) throws Exception {
Outdb doit = new Outdb();

Runtime.getRuntime().addShutdownHook(doit);
Signal sigTERM = new Signal("TERM");/* 注册KILL信号 */
Signal sigINT = new Signal("INT");/* 注册CTRL+C信号 */
doit.oldHandler = Signal.handle(sigTERM, doit);
doit.oldHandler = Signal.handle(sigINT, doit);
...................



}
}



程序主要用SignalHandler进行信号监听,信号处理方法signalCallback中进行执行退出;
同时Runtime.getRuntime().addShutdownHook(doit);注册了程序退出处理函数;
但是在程序执行过程中,当收到CTRL+C信号之后,虽然执行了信号处理函数和退出处理函数,但是Main主线程
没有立刻停止。

请教各位,如何控制当接收到信号之后将MAIN线程挂起?
...全文
498 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
baihuihui 2010-03-12
  • 打赏
  • 举报
回复
你的意思是在接受到信号时在signalCallback 回调函数中改变一个状态值A为真,然后在主线程中判断A值为真时候推出并修改状态量B为TRUE ,然后RUN线程中WHILE(B)是这样吗?

[Quote=引用 21 楼 yueguangkai001 的回复:]
在线程中run方法中使用while(条件)//而不是true
在你关闭主程序之前,让条件变成false,其他线程就能够自动执行完成
[/Quote]
baihuihui 2010-03-11
  • 打赏
  • 举报
回复
我再给仁兄解释清楚下哈
我本意是想完善JAVA程序完成对CRTL+C,KILL系统信号处理。当一个程序接收到信号时候,会调用
signalCallback程序进行信号处理:
方案一:原先在signalCallback 中调用了SYSTEM.EXIT(1)退出,此时程序就会执行到一开始注册的退出处理线程Runtime.getRuntime().addShutdownHook(doit)该线程对数据库对象进行关闭操作以及异常文件删除操作,本来程序到此为止应该结束了,但是MAIN函数还是会继续执行一小段代码才退出。
方案二:也是我现在用的牵强的办法,当接收到信号时signalCallback修改了一个状态量STATUS以此告诉主线程退出,在MAIN代码中加了多段代码对这个STATUS进行判断,如果执行退出,最后调用注册的退出线程


引用 18 楼 preferme 的回复:
因为代码不完整,所以,理解可能有误。
程序设计当中,是比较忌讳System.exit(0)语句出现的,
应该想一个较为合理的程序结构进行应用程序的关闭操作。

System.exit的出现,会使程序出现一个入口(main函数)多个出口的现象,
这样有可能会对其他部分产生影响。

比如一个JVM运行多个应用程序的情况,就会非常危险。
一个Tomcat上部署多个项目,你上来一个System.exit,整个Tomcat都关了。

怎么才能更好的是程序退出呢 ?
我想,应该让每个线程的程序结构,都要合理化,当程序要关闭时,让run方法自然跳转到末尾。

当程序资源都关闭了,程序还没有立即结束。
说明,某个线程的run(或者主线程的main)方法没有立即跳转到末尾结束。
一般情况,是由于线程请求资源未得到而被阻塞了。
比如:ServerSocket.accept()方法,
当没有客户端连接上来,ServerSocket.accept()的调用线程是被阻塞的。
还比如:阻塞队列中没有元素的时候,还要获得元素的情况下,获取元素的线程也会被阻塞。

当然,楼主的情况,我就看不明白了。

额~~~
baihuihui 2010-03-11
  • 打赏
  • 举报
回复
你贴这个何义啊?

引用 17 楼 qqcrazyboy 的回复:
package Thread;

public class TwoThread {
public static void main(String[] args) {
Queue q=new Queue ();//new出一个q:后面的两个线程都是用的同一个q,保证一个put一个get
Producer p=new Producer (q);//让new出的p去往q里面put
Customer c=new Customer (q);//让new出的c从q中get
p.start();//p和q开始的顺序并不报错
c.start();

}
}
class Producer extends Thread
{
Queue q;
public Producer(Queue q) {
this.q=q;//给成员变量赋值,再一调运q的put方法
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
q.put(i);//此处只是让q去put  10次
System.out.println("Producer put "+i);//并且输出本次放的是第几杯
}
}
}
class Customer extends Thread
{
Queue q;
public Customer(Queue q) {
this.q=q;//给成员变量赋值,再一调运q的get方法
}
@Override
public void run() {
while (true) {//死循环:只要q里面有,就去get
//get方法有返回值,返回值就是producer所put的数量
//此处也不需要去考虑是第几杯
//在Queue中的value解决可这一问题:
//put中的I赋给value,get方法有返回值就value的值
System.out.println("Customer get "+q.get());
//如果循环完了,就跳出循环,否则线程不会自己结束
if (q.value==9) {
break;
}
}

}
}
class Queue
{
int value;
boolean bFull=false;
public synchronized void put (int i)//在producer中的put方法中就是将其I传进来
{
if (!bFull) {//条件为真(如果没满,就倒水)
value=i;//给value赋值,现在有几杯水
bFull=true;//满了
notify();//唤醒其他线程(让customer去get)
}
try {
wait();//告诉customer去get后自己等待customer的get结束
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized int get()
{
if (!bFull) {//如果没满就等待,如果满了就不进    **这就是为什么main里面谁先开始不报错的原因**
//get和put方法中的if条件判断起到了至关重要的作用
try {
wait();
} catch (InterruptedException e) {

e.printStackTrace();
}
}
bFull =false;//赋值为没满
notify();//唤醒producer去put
return value;//get的返回值就是put的时候给value赋的值
}
}
xpzhou 2010-03-11
  • 打赏
  • 举报
回复
严重支持楼主
yueguangkai001 2010-03-11
  • 打赏
  • 举报
回复
在线程中run方法中使用while(条件)//而不是true
在你关闭主程序之前,让条件变成false,其他线程就能够自动执行完成
智鹿软件 2010-03-03
  • 打赏
  • 举报
回复
package Thread;

public class TwoThread {
public static void main(String[] args) {
Queue q=new Queue ();//new出一个q:后面的两个线程都是用的同一个q,保证一个put一个get
Producer p=new Producer (q);//让new出的p去往q里面put
Customer c=new Customer (q);//让new出的c从q中get
p.start();//p和q开始的顺序并不报错
c.start();

}
}
class Producer extends Thread
{
Queue q;
public Producer(Queue q) {
this.q=q;//给成员变量赋值,再一调运q的put方法
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
q.put(i);//此处只是让q去put 10次
System.out.println("Producer put "+i);//并且输出本次放的是第几杯
}
}
}
class Customer extends Thread
{
Queue q;
public Customer(Queue q) {
this.q=q;//给成员变量赋值,再一调运q的get方法
}
@Override
public void run() {
while (true) {//死循环:只要q里面有,就去get
//get方法有返回值,返回值就是producer所put的数量
//此处也不需要去考虑是第几杯
//在Queue中的value解决可这一问题:
//put中的I赋给value,get方法有返回值就value的值
System.out.println("Customer get "+q.get());
//如果循环完了,就跳出循环,否则线程不会自己结束
if (q.value==9) {
break;
}
}

}
}
class Queue
{
int value;
boolean bFull=false;
public synchronized void put (int i)//在producer中的put方法中就是将其I传进来
{
if (!bFull) {//条件为真(如果没满,就倒水)
value=i;//给value赋值,现在有几杯水
bFull=true;//满了
notify();//唤醒其他线程(让customer去get)
}
try {
wait();//告诉customer去get后自己等待customer的get结束
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized int get()
{
if (!bFull) {//如果没满就等待,如果满了就不进 **这就是为什么main里面谁先开始不报错的原因**
//get和put方法中的if条件判断起到了至关重要的作用
try {
wait();
} catch (InterruptedException e) {

e.printStackTrace();
}
}
bFull =false;//赋值为没满
notify();//唤醒producer去put
return value;//get的返回值就是put的时候给value赋的值
}
}
冰思雨 2010-03-03
  • 打赏
  • 举报
回复
因为代码不完整,所以,理解可能有误。
程序设计当中,是比较忌讳System.exit(0)语句出现的,
应该想一个较为合理的程序结构进行应用程序的关闭操作。

System.exit的出现,会使程序出现一个入口(main函数)多个出口的现象,
这样有可能会对其他部分产生影响。

比如一个JVM运行多个应用程序的情况,就会非常危险。
一个Tomcat上部署多个项目,你上来一个System.exit,整个Tomcat都关了。

怎么才能更好的是程序退出呢 ?
我想,应该让每个线程的程序结构,都要合理化,当程序要关闭时,让run方法自然跳转到末尾。

当程序资源都关闭了,程序还没有立即结束。
说明,某个线程的run(或者主线程的main)方法没有立即跳转到末尾结束。
一般情况,是由于线程请求资源未得到而被阻塞了。
比如:ServerSocket.accept()方法,
当没有客户端连接上来,ServerSocket.accept()的调用线程是被阻塞的。
还比如:阻塞队列中没有元素的时候,还要获得元素的情况下,获取元素的线程也会被阻塞。

当然,楼主的情况,我就看不明白了。

额~~~
baihuihui 2010-02-25
  • 打赏
  • 举报
回复
又测验了把,如果signalCallback只有System.exit(0);语句,程序会立刻退出,但是如果添加了处理函数主线程就就没有那么快结束了
east_java 2010-02-25
  • 打赏
  • 举报
回复
可以看看 Java线程专题 http://www.java1995.cn/wiki/topic/6
chenpupeng 2010-02-25
  • 打赏
  • 举报
回复
有关java多线程的知识,还是看看这里吧,介绍的比较全面http://www.itkanba.com/bbs/forumdisplay.php?fid=13&filter=type&typeid=10
牛叔 2010-02-24
  • 打赏
  • 举报
回复
给你顶个。。。。
kill
小贝壳666 2010-02-24
  • 打赏
  • 举报
回复
signalCallback方法中的System.exit(0);是停止JVM,执行这个语句,MAIN线程就终止了。。
guyuxuelang 2010-02-24
  • 打赏
  • 举报
回复
路过,看不懂,帮你顶一下
baihuihui 2010-02-24
  • 打赏
  • 举报
回复
引用 9 楼 gardner2010 的回复:
signalCallback方法中的System.exit(0);是停止JVM,执行这个语句,MAIN线程就终止了。。



因为我原先的方法是在signalCallback中调用一个appExit()函数做清理操作,在appExit()中会执行sysmte.exit(0)退出;但是主线程还是会继续执行。
baihuihui 2010-02-24
  • 打赏
  • 举报
回复
引用 11 楼 yueguangkai001 的回复:
你的主程序挂起了,还有其他的线程在监听你的主程序是否再次启动了么?
  如果没有,那你的意思就是接受到信号的时候关闭程序,我认为那挂起没有任何意义


对,我本意即是当接收到信号,调用比如关闭数据库连接等操作清理函数之后再关闭程序,但是在signalCallback中调用完清理函数appExit()之后,主线程还是会运行一会才会结束;

于是我采用现在贴的程序方式,在signalCallback中调用system.exit(0),然后再一开始就注册了一个
线程Runtime.getRuntime().addShutdownHook(doit) 注册了程序退出处理函数;结果当接收到信号
之后, signalCallback与addShutdownHook线程执行完,主线程还在继续执行
yueguangkai001 2010-02-24
  • 打赏
  • 举报
回复
你的主程序挂起了,还有其他的线程在监听你的主程序是否再次启动了么?
如果没有,那你的意思就是接受到信号的时候关闭程序,我认为那挂起没有任何意义
baihuihui 2010-02-23
  • 打赏
  • 举报
回复
引用 4 楼 vvflying 的回复:
代码运行不了,好难看懂。偶开个玩笑:System.exit(0);


呵呵,抱歉。。因为大多了,不能全贴
baihuihui 2010-02-23
  • 打赏
  • 举报
回复
引用 2 楼 gardner2010 的回复:
LZ说的应该不是MAIN线程挂起,而是MAIN线程退出



是的,关键就接收到信号之后,让MAIN线程终止。。
baihuihui 2010-02-23
  • 打赏
  • 举报
回复
引用 1 楼 gardner2010 的回复:
Java codeSignal sigTERM=new Signal("TERM");/* 注册KILL信号*/
Signal sigINT=new Signal("INT");/* 注册CTRL+C信号*/if (!stopFlag) {
doit.oldHandler= Signal.handle(sigTERM, doit);
}else {
exit;
}if (!stopFlag) {
doit.oldHandler= Signal.handle(sigINT, doit);
}else {
exit;
}
...................

可以抽出一个模板方法让代码更简洁



我再描述清楚点吧,,,
就是接收到信号之后执行完注册的退出处理线程之后,MAIN线程还会继续运行代码
vvflying 2010-02-23
  • 打赏
  • 举报
回复
代码运行不了,好难看懂。偶开个玩笑:System.exit(0);
加载更多回复(3)

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧