频道栏目
首页 > 资讯 > 其他综合 > 正文

浅谈利用线程的生命周期使小球撞墙弹回

16-04-06        来源:[db:作者]  
收藏   我要投稿

线程的生命周期

试了一下代码应该看到了动画了吧,小球确实是动起来了。只是和想象的有所差别,小球飞的实在是太快了。现在想法就是怎么样才能使小球优雅的,至少是以可控制的速度飞行。我们的思路是,能不能每次在y++以后,让线程等待一会儿,那就再重画。其实有一条指令是可以让线程休眠的,这是一个类方法——Thread.sleep()。

try{
Thread.sleep(30);
}catch(Exception e){}
异常处理的写法是,try后面跟的大括弧保护了有可能出现异常的代码,我们这里写的线程休眠30毫秒。catch后面的大括弧里面放的是万一出现了异常怎么处理,catch后面跟的小括弧很像是方法的参数,这还少有人给的内容,内容放在e里面;这就是系统的内容,放的是发生了什么事情。这个例子中,我们不做任何处理,睡死就睡死好了,无所谓的事情,所以catch后面的大括弧就这么放着,什么内容都没有,这种事情常常会发生,但是你不能写try catch。
import java.awt.*;
public class MyBall {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Frame w = new Frame();
        w.setSize(300, 400);

        MyOval mp = new MyOval();
        w.add(mp);

        Thread t  = new Thread(mp);
        t.start();

        w.show();
    }

}
class MyOval extends Panel implements Runnable{
    int x=30,y=30;
    public void paint(Graphics g){
        g.fillOval(x, y, 20, 20);
}
    public void run(){
        while(true){
        y++;
        if(y>400){
            y=0;
        }
        try{
            Thread.sleep(30);
        }catch(Exception e){}
        repaint();
    }
    }
}

继续上一次的小球代码加上线程休眠的指令,小球是不是慢慢动起来了,可能有些人的操作系统中的小球会闪的很厉害,这个问题暂时先别管,后续我会跟你们一起解决这个问题。
现在小球可以慢慢的垂直落下,能不能让这个小球斜着飞,这个不难,那么还有没有办法让小球弹回来呢?
代码自己写过几遍之后,我借此讨论一下线程的生命周期。
可以理解在new Thread()后,我们就在内存里得到了一个进程对象,这样线程对象和其它对象没有区别,安静地待在内存里,我们称呼这种状态叫做新建状态。
当调用了start方法之后,线程就启动了,但是这并不意味着run方法中的代码会立刻被执行,start方法也就是通知系统,自己做好了准备,可以被轮转了,所以我们称这种状态为就绪状态。
这里要注意的是,由于run是一个正常方法,也是可以被调用的,但是你不能直接调用run方法,这么做线程机制就不存在了,run方法就成了一个普通的方法了,让线程处于就绪状态的只有start方法。
至于线程什么时候进入运行状态,都不是我们程序员能够控制的了,这取决于线程调度机制的调度。但是你能理解,线程不能一直处于运行状态,当CPU轮转到其他线程时,线程将回到就绪状态。
在这个例子中,使用了sleep,在sleep起作用的时候,线程处于阻塞状态,还有其他的阻塞语句会让线程处于阻塞状态,当线程处于阻塞状态时,CPU不会轮转到这个线程上。
在run方法执行结束后,线程就处于死亡状态。
这样我们知道线程会有创建,就绪,运行,阻塞,死亡5种状态。
另外,线程还有优先级,优先级高的线程将获得更多的执行机会,最小的优先级1,最大的优先级是10,普通优先级是5,线程的默认优先级和创建它的父线程相同,在我们的例子中父线程是main线程,main线程具有普通优先级5,可以通过t.setPriority(6)来改变优先级。
问题是,不同的操作系统对线程的优先级支持是不同的,所以要尽量避免直接设置优先级数字,而是使用Thread.MAX_PRIORITY,Thread.MIN_PRIORITY,Thread.NORM_PRIORITY这样的常量来设置,JVM会协调操作系统。
## 小球碰撞 ##
不知道小球遇到墙反弹你的想法是什么,我们还是一样现将任务分解:
1.做个窗体
2.做个小球
3.让小球斜着飞
4.遇到墙反弹
罗列出来以后发现好像也就第四步我们没有讲解过,那么我们可以从斜着飞的代码开始。

class MyOval extends Panel implements Runnable{
    int x=30,y=30;
    public void paint(Graphics g){
        g.fillOval(x, y, 20, 20);
}
    public void run(){
        while(true){
            x++;
        y++;
        if(y>400){
            y=0;
        }
        try{
            Thread.sleep(30);
        }catch(Exception e){}
        repaint();
    }
    }

我们先得到了一个能够向右下角斜着飞的小球,下一步要判断墙在哪儿。之前我们已经用代码判断出了下面的墙,下一步就是见到墙以后,小球应该反弹回来,一个向右下飞行的小球遇到右边的墙。应该向左下飞行,如果做到,x++,y–.

class MyOval extends Panel implements Runnable{
    int x=30,y=30;
    public void paint(Graphics g){
        g.fillOval(x, y, 20, 20);
}
    public void run(){
        while(true){
        x++;
        y++;
        if(y>300){
            x--;
            y++;
        }
        try{
            Thread.sleep(30);
        }catch(Exception e){}
        repaint();
    }
    }
    }

不过从结果上看小球没有反弹,而是消失在右边的墙体里了,我们来分析一下为什么会这样。我们判断墙的代码是if(x>300){},问题是,小球的坐标是左上角的坐标,如果用x和300比较,必须是整个小球小球都进入了右边的墙角里,才能够符合条件,加上设置窗体的大小为300*400,这个值指的是窗体整体的大小,窗体里面的白色区域要比这个值小,白色区域的大小差不多是283,361(其实我无法保证你的电脑也是这个值,还是要自己去试一下),我们看到横向的窗体边框占了17个像素点,纵向上占了39个像素点,因为窗体上面有一个放标题的蓝色区域,我们修正以后,判断墙的值就变成了if(x<263){},小球的直径一并去掉。
墙是个问题,但是真正的问题是,小球咋就飞回来呢?你别光看着我这样磨叽,别让我一直带你们飞,最好还是自己找到解决办法,我们看到小球在墙的边缘时,就是x=263,当然y=263,代码遇到x++,y++以后,x=264,y=264,程序循环回来,是不是符合if的条件了,现在x–,y++,这样x=263,y=265。程序又循环回来,又遇到了x++,y++,x=264,y=266,再次符合条件,x的值又被减去1.看出来什么问题了吗?虽然x–了,但是立刻又被++回去,结果就是x的值一直不变,y以两倍的速度变大,小球贴着墙边滑下去了。也就是说我们减x的值得时候,就不要再加了。

class MyOval extends Panel implements Runnable{
    int x=30,y=30;
    public void paint(Graphics g){
        g.fillOval(x, y, 20, 20);
}
    public void run(){
        while(true){
            if(x>263){
        x++;
        y--;
            }
            else {
            x++;
            y++;
        }
        try{
            Thread.sleep(30);
        }catch(Exception e){}
        repaint();
    }
    }
}

我从未讲过if循环语句,我认为不需要,你完全可以根据遇见的结果去认识这个if语句,很多知识都可以被猜出来,学习能力强的马上就能理解。
试一下,好像小球还是没有反弹,还是来思考一下,问题到底出在哪里?怎么去解决?我们拿墙做判断条件,当小球反弹后,便离开墙,一旦离开墙,反弹的条件就不满足了,小球又会恢复右下方飞行,能不能遇到墙,改变了飞行姿态后,就固定下来这个飞行姿态,而和墙没有关系。在程序设计过程中,我们常常在逻辑遇到困难的时候,想到通过增加变量来解决问题,根据上面的描述,我们增加一个变量来解决问题,根据上面的描述,我们增加一个变量来存储当前的飞行姿态,并且实先这样来
这里写图片描述

class MyOval extends Panel implements Runnable{
    int x=30,y=30;
    int att =0;//0有下,1左下,2左上,3右上
    public void paint(Graphics g){
        g.fillOval(x, y, 20, 20);
}
    public void run(){
        while(true){
            if(att==0){
        x++;
        y--;
            }
            if(att==1) {
            x--;
            y++;
        }
            if(att==2){
                x--;
                y--;
            }
            if(att==3){
                x++;
                y--;
            }
            //改变飞行姿态
        try{
            Thread.sleep(30);
        }catch(Exception e){}
        repaint();
    }
    }
}

这段代码使用了注释,体会一下如果没有注释,要不了多久就会忘了开始的定义,思路就会乱掉,其中改变飞行姿态的代码还没有提供,我想目前的代码还是可以理解的。
我们再来看改变飞行姿态的代码,并不是简单的0变成1,1变成2,2变成3,3变成0这么简单,,每面墙有两个可能飞来的方向,也有两个反弹出去的方向,所以反弹代码要对飞来的方向进行判断。下面是改变飞行方向的代码
//改变飞行方向

//改变飞行姿态
    if(x>263){
        if(att==0){
            att=1;
        }else{
            att=2;
        }
    }
    if(y>341){
        if(att==1){
            att=2;
        }else{
            att=3;
        }
    }
    if(x<0){
        if(att==2){
            att=3;
        }else{
            att=0;
        }
    }
    if(y<0){
        if(att==3){
            att=0;
        }else{
            att=1;
        }
    }

将上述代码结合就能看家年最后的效果了
我把代码整合写一遍

import java.awt.*;
public class MyBall {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Frame w = new Frame();
        w.setSize(300, 400);

        MyOval mp = new MyOval();
        w.add(mp);

        Thread t  = new Thread(mp);
        t.start();

        w.show();
    }

}
class MyOval extends Panel implements Runnable{
    int x=30,y=30;
    int att=0; //0右下,1左下,2左上,3右上
    public void paint(Graphics g){
        g.fillOval(x, y, 20, 20);
}
    public void run(){
        while(true){
            //定义飞行姿态
            if(att==0){
        x++;
        y++;
            }
        if(att==1){
            x--;
            y++;
        }
        if(att==2){
            x--;
            y--;
        }
        if(att==3){
            x++;
            y--;
        }
        //改变飞行姿态
    if(x>263){
        if(att==0){
            att=1;
        }else{
            att=2;
        }
    }
    if(y>341){
        if(att==1){
            att=2;
        }else{
            att=3;
        }
    }
    if(x<0){
        if(att==2){
            att=3;
        }else{
            att=0;
        }
    }
    if(y<0){
        if(att==3){
            att=0;
        }else{
            att=1;
        }
    }
        try{
            Thread.sleep(30);
        }catch(Exception e){}
        repaint();
    }
}
}

今天的就更新到这里,下期再见

 
 
相关TAG标签
上一篇:JAX-WS指南分享(翻译自apache)
下一篇:微信营销方案怎么写 怎么考核运营业绩
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站