软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 编程语言 -> 如何利用线程的生命周期使小球撞墙弹回 -> 正文阅读

[编程语言]如何利用线程的生命周期使小球撞墙弹回


线程的生命周期


试了一下代码应该看到了动画了吧,小球确实是动起来了。只是和想象的有所差别,小球飞的实在是太快了。现在想法就是怎么样才能使小球优雅的,至少是以可控制的速度飞行。我们的思路是,能不能每次在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语句,很多知识都可以被猜出来,学习能力强的马上就能理解。
试一下,好像小球还是没有反弹,还是来思考一下,问题到底出在哪里?怎么去解决?我们拿墙做判断条件,当小球反弹后,便离开墙,一旦离开墙,反弹的条件就不满足了,小球又会恢复右下方飞行,能不能遇到墙,改变了飞行姿态后,就固定下来这个飞行姿态,而和墙没有关系。在程序设计过程中,我们常常在逻辑遇到困难的时候,想到通过增加变量来解决问题,根据上面的描述,我们增加一个变量来解决问题,根据上面的描述,我们增加一个变量来存储当前的飞行姿态,并且实先这样来
[img]http://img.blog.csdn.net/20160403150023590
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();
    }
}
}

今天的就更新到这里,下期再见
......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-03 20:43:25  
编程语言 最新文章
Java面试题(1)
ReactiveX序列——RxSwift
C++STL之ACM相关知识大全
c++中vector向量几种情况的总结(向量指针,
SSH框架整合demo
JAX
UVA
curl备忘(1)
C#机房重构——万事开头难(二)
OJ刷题
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年1日历
2018-1-23 3:52:45
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --