JAVA线程对象管理

    首先JAVA大神可以对此一笑而过,因为作者是一个C++方向的开发人员,该文仅记录开发过程中的问题,并希望在错误之处得到纠正

    从事多年C++开发后,一个偶然的机会接触到一个JAVA的项目,刚接手的时候除了语法其他都是按照C++的习惯来编码的,在编码的过程中,初始化的时候很自然的new出了一个对象,但是当我想删除这个对象的时候,又很自然的写出了delete xxx; 这下问题大了,好像JAVA里没有这个关键字?反正我编译错误了。后来想了想,JAVA可以很强大的把垃圾回收啊,没有必要像C++一样要手动删除的。从那以后一直没关注过这类问题,直到后来一次评审其他人的代码时,发现了下面的有趣的问题。

    首先看一下如下的代码:

   

public void restart() {
    if (null != mXXXThread) {
        mXXXThread.cancel();
        mXXXThread = null;
    }

    if (null == mXXXThread) {
        mXXXThread = new XXXThread();
        mXXXThread.start();
    }
}


    大概意思是说要重新启动一个线程,在停止该线程后,直接将该对象设置为null,然后重新创建一个对象,并启动这个线程。

    这段代码没什么错误,也可以很好的运行,至少一段时间内没有在这里出过问题。

    但是,创建一个线程并启动,这是一个耗费资源的过程,并且上述的代码如果直接将对象赋值为null,是否一定能保证那个线程就会销毁么?由于JAVA经验较少,并不能确定该代码的正确性,还请JAVA大神解答。

    究竟为什么对这么小的问题耿耿于怀,一方面是不能自己释放一个东西感到不快,另一方面是公司的代码检查不允许直接将一个对象赋值为null。

    大家都知道,创建一个线程是耗费资源的,理论都知道,但是写代码的时候就和这些理论说拜拜了。大部分的软件公司的员工都会写出这样的代码,放眼看去一定是没问题的,但是当你觉得软件慢了,性能不佳了,这些小地方都是问题。

    最初想象使用同一个对象,仅生成一次,该线程停止后再调用一次start,于是有了如下的代码:

public void restart()
{
    mXXXThread.cancel();
    if (mXXXThread.isAlive()) {
        mXXXThread.join();
    }

    mXXXThread.setparam(param);
    mXXXThread.start();
}


    很强迫症的要确定上一个线程停止后再重新设置参数并启动线程,不必重新生成一次对象,只要重新启动一次线程就好。

    看到这里大神一定看出了一个很严重的错误:线程不可以重复start!!!!!!!

    好吧,天真一次。如何重复利用一个对象呢?这次看到了线程池。

    Executor提供了4种线程池,作为JAVA新手我不过多介绍,满足我的使用条件的仅有SingleThreadExecutor。

    该线程池的好处就是单线程池,控制仅有一个线程在运行。

    将原来的Thread的子类改成实现Runnable接口的类,一切都解决,我不再需要关心线程停止后再重新开启线程,甚至我可以一直使用一个Runnable对象而不需要重新创建,代码如下:

   

public xxxRunnable implements Runnable {
     private boolean mStop = false;    
public void setparam(int param)
    {
         //save param
    }
    
    public void cancel()
    {
         mStop = true
    }
    public void run()
    {
        mStop = false;
        //do something with param
        while (!mStop) {
         //working
         }
    }
}


     上述为Runnable的实现代码,不太善于使用stop的方法停止线程,所以使用标志位的方式停止线程。可以看到,设置参数后,在线程真正运行时才会使用这些参数。而restart代码如下:

public void restart()
{
    mXXXRunnable.cancel();
    mXXXRunnable.setparam();
    mSingleExecutor.executor(mXXXRunnable);
}


    这就能重新运行?

    cancel之后线程不会停止吧,马上设置参数不会影响上一个线程运行么?这就要根据实际的业务逻辑需要了。这里我说不会影响,因为适合我的逻辑,因为传入的参数是一个socket,而我在过程中实际需要的是InputStream……在run中我会通过socket来获取它的inputstream,所以就算外界设置了其他的socket,也不会影响当前的run(),但是这不是重点,重点是线程池在上次的线程停止运行后执行新的线程,也就是重新设置了参数的runnable,好了,不用重新生成对象了,虽然有点冒险,好在避过检查了。

    对于JAVA的对象管理,习惯了new出的对象必须要delete之后,就不太习惯JAVA,也许天生苦命,就是喜欢挑战内存泄漏。不过,对于线程,始终很感兴趣,因为很多的项目失败在多线程和多进程,类似于上述代码,如果稍微复杂的逻辑我想一定会出问题,如果多个线程使用同一份数据更会出问题,如何控制好线程的管理,不只是一个技术,更是一种艺术。

    作为新手抛砖引玉,希望得到更多指导。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值