目录
1 关于线程
2 实现线程
3 线程游戏v1.0:让小球可以不停的在界面游动
1 关于线程
程序执行时,是单任务执行,有多个任务时会按顺序执行。
e.g. 两个任务按顺序执行。
public class Thread01{
public static void main(String[] args){
int count = 0;
for(int i = 0; i < 10; i++){
count++;
}
System.out.println ("任务1执行完成:" + count);
int count1 = 10;
for(int i = 10; i > 0; i--){
count1--;
}
System.out.println ("任务2执行完成:" + count1);
}
}
运行结果
任务1执行完成:10
任务2执行完成:0
可以看到,“任务1”率先被完成,然后“任务2”才被完成。
如果希望多个任务同时被执行,则需要引入新的机制。
2 实现线程
①继承:extends Thread类
②实现接口:implements Runnable接口
同时,重写 run 方法:将需要被执行的任务写入 run 方法中。
e.g. 分别使用继承和实现接口操作,将任务1和任务2写入两个类的 run 方法中。
public class ThreadDemo1 extends Thread{
@Override
public void run(){
for(int i = 0; i < 100; i++){
System.out.println ("线程1执行中:" + i);
}
}
}
public class RunnableDemo1 implements Runnable{
@Override
public void run(){
for(int i = 0; i < 100; i++){
System.out.println ("线程2执行中:" + i);
}
}
}
在主线程main中,创建Thread对象,调用Thread对象的启动方法,即可启动该线程。
public class Test {
public static void main(String[] args) {
ThreadDemo1 td1 = new ThreadDemo1();
RunnableDemo1 rd1 = new RunnableDemo1();
// Thread t1 = new Thread (td1);
Thread t2 = new Thread(rd1);
td1.start();
t2.start();
}
}
上述代码中,创建 t2 时使用的Thread构造方法是:
public Thread(Runnable task) {
this(null, null, 0, task, 0, null);
}
main 线程执行完 start 方法后就结束了,具体任务的执行过程由这些任务的线程来执行。
run 方法执行完成后,它所在的线程结束。
任何Java程序都是多线程程序。
3 线程游戏v1.0:让小球可以不停的在界面游动
①创建界面类 GameUI,继承 JFrame 类,设置界面参数,启动小球线程;
import javax.swing.*;
public class GameUI extends JFrame {
int ballCounts = 10;
Ball[] balls = new Ball[ballCounts];
void initUI() {
//设置界面参数
setTitle("线程游戏");
setSize(800, 600);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//启动小球线程,在 main 主线程中调用本方法以启动
for (int i = 0; i < ballCounts; i++) {
balls[i] = new Ball();
balls[i].g = getGraphics();
balls[i].start();
}
}
}
②创建小球类 Ball,继承 Thread 类,重写 run 方法,绘制小球,且每隔若干毫秒更新一次小球位置,使其运动起来。
import java.awt.*;
import java.util.Random;
public class Ball extends Thread {
//创建画笔对象,以便下文调用绘制小球的 setColor 和 fillOval 方法
Graphics g;
int x;
int y;
int speedX;
int speedY;
Color color;
//随机数对象,以便下文调用生成随机数的 nextInt 方法
Random random = new Random();
@Override
public void run() {
x = random.nextInt(800);
y = random.nextInt(600);
speedX = setSpeed();
speedY = setSpeed();
color = new Color(random.nextInt(Integer.MAX_VALUE));
g.setColor(color);
for (int i = 0; ; i++) {
//sleep函数,每隔4ms更新一次小球位置
try {
Thread.sleep(4);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
g.fillOval(x, y, 30, 30);
x += speedX;
y += speedY;
//小球碰到边界时,以原速度反弹
if (x <= 0 || x >= 770) {
speedX = -speedX;
}
if (y <= 0 || y >= 570) {
speedY = -speedY;
}
}
}
//设置小球速度。为防止小球不动,要求返回的速度值不为0
int setSpeed(){
int speed = random.nextInt(4) - 2;
if (speed == 0){
speed = setSpeed();
}
return speed;
}
}
③Test 类,运行 main 主线程。
public class Main {
public static void main(String[] args) {
//调用 initUI 方法,设置界面对象属性,启动新线程,一举两得
//执行完所有线程的 start 方法后,main 线程将结束
//由于 run 方法中存在死循环,这些管理小球的线程都不会自动结束
//窗体也是一个单独的线程,可以通过在下文添加输出语句来佐证,经验证,输出语句照常执行
//程序退出时间为窗体GameUI线程的结束时间,即窗体关闭的时间
new GameUI().initUI();
}
}