1、锁synchronized
public class Good extends Thread {
private static int num = 10;
@Override
public void run() {
while (num > 1) {
try {
Thread.sleep(1000);
buyOne();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void buyOne() {
num--;
System.out.println(getName() + ",剩余数量:" + num);
}
}
以上为一个商品类,数量为10,每次执行buyOne就会买走一个商品。正常情况下只有当商品数量大于0时,才能买走商品,但是如果有两个线程同时访问该方法 就会出现两个人买到同一件商品。甚至出现商品数量为负数的情况,所以为了避免出现这种情况,给相应的方法加上锁
private static final Object OBJ = new Object();
private void buyOne() {
synchronized (OBJ) {
num--;
System.out.println(getName() + ",剩余数量:" + num);
}
}
2、坦克四向运动
绘制四个方向的坦克图片置于panel中,四张图片文件名最后一位通过字母的d,s,a,w来区分。这样方便后面控制坦克移动,接下来是实现代码和简单解释
/*
为了方便后期的阅读和升级,这里将地图上的各个精灵(包括地图)分别封装到不同的类中
*/
import com.woniu.javaweek04.javaday23.tank_game.model.MyMap;
import com.woniu.javaweek04.javaday23.tank_game.model.MyTank;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class StagePanel extends JPanel implements Runnable, KeyListener {
private MyMap myMap = new MyMap();
private MyTank myTank = new MyTank();
@Override
public void run() {
while (true) {
gameUpdate();
try {
Thread.sleep(6);
} catch (InterruptedException e) {
e.printStackTrace();
}
repaint();//坐标改变后重新绘制图片
}
}
private void gameUpdate() {
myTank.update();
}
@Override
public void paint(Graphics g) {
myMap.setG(g);
myMap.setStage(this);
myMap.show();
myTank.setG(g);
myTank.setStage(this);
myTank.show();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {//键盘按压监听
int key = e.getExtendedKeyCode();
//以下四个分支分别代表长按dsaw或上右下左上,可以操控坦克的移动
//将我方坦克的cmd设置为对应字符
if (key == 39 || key == 68) {
myTank.cmd = "dd";
} else if (key == 40 || key == 83) {
myTank.cmd = "ss";
} else if (key == 37 || key == 65) {
myTank.cmd = "aa";
} else if (key == 38 || key == 87) {
myTank.cmd = "ww";
}
}
@Override
public void keyReleased(KeyEvent e) {//键盘释放监听
int key = e.getExtendedKeyCode();
//以下四个分支分别代表从dsaw或上右下左上松开
if (key == 39 || key == 68) {
myTank.cmd = "d";
} else if (key == 40 || key == 83) {
myTank.cmd = "s";
} else if (key == 37 || key == 65) {
myTank.cmd = "a";
} else if (key == 38 || key == 87) {
myTank.cmd = "w";
}
}
}
以下是目前实现好的我方坦克类
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
public class MyTank {
private Graphics g;
private JPanel stage;
private int x = 0;
private int y = 0;
public String cmd = "d";
public Graphics getG() {
return g;
}
public void setG(Graphics g) {
this.g = g;
}
public JPanel getStage() {
return stage;
}
public void setStage(JPanel stage) {
this.stage = stage;
}
public void show() {
Image img = null;
try {
img = ImageIO.read(new File("staticTank/mytank-" + cmd.substring(0, 1) + ".png"));//不论是cmd是一个字符还是两个字符,都能使得坦克朝向正确的方向
} catch (IOException e) {
e.printStackTrace();
}
g.drawImage(img, x, y, 64, 64, stage);
}
public void update() {
//StagePanel通过监听键盘获得坦克对应的字符
//根据对应字符控制x,y数值的加减,实现坦克的坐标变化,以此达到移动的效果
if ("dd".equals(cmd)) {
x++;
} else if ("ss".equals(cmd)) {
y++;
} else if ("aa".equals(cmd)) {
x--;
} else if ("ww".equals(cmd)) {
y--;
}
}
}