2013-05-17 22:14:36Morris
[JAVA][作業] 練習線程
設計一個可以鍵盤監聽、滑鼠監聽。
只要有動作,就將可以自由碰撞的按鈕增加一個。
這作業有一個討論的問題:
Race condition (競態條件)
也就是因為有很多線程,再處理的時候會爭奪資源,誰先誰後就變得很重要。
因此有可能會發生無法接受鍵盤監聽與滑鼠監聽,基本上感覺起來就是相當不靈敏。
最後使用 Timer.class 去解決,我想很重要原因是 Thread.sleep() 會導致整個 class 暫停?
同時也會發現,Java 有很多觸發事件,但很多觸發事件都是單線程的,
即不會在一個觸發事件處理中時,同時再次觸發,後者會被撞擊掉(忽略)。
package ce1002.E6.s100502205;
import java.awt.Graphics;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;
import java.util.Timer;
import java.util.TimerTask;
public class E6 extends JFrame implements KeyEventDispatcher {
public final int btnWidth = 50;
public final int btnHeight = 50;
public final int Width = 450;
public final int Height = 450;
boolean runable = false, addIng = false;
int totButton = 0;
public static Vector<MovingButton> buttonList;
public E6() {
this.setTitle("E6");
this.setSize(Width, Height);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setLayout(null);
this.buttonList = new Vector<MovingButton>();
addDouble();
this.setVisible(true);
Timer timer = new Timer();
timer.schedule(new Process(), 100, 30);
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventDispatcher(this);
}
class Process extends TimerTask {
public void run() {
if (!addIng) {
for (MovingButton bb : buttonList)
bb.adjust();
repaint();
} else {
}
}
}
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_RELEASED)
return false;
addDouble();
return false;
}
public void addDouble() {
addIng = true;
MovingButton tmp = new MovingButton(this.getWidth() / 2,
this.getHeight() / 2, btnWidth, btnHeight, this);
buttonList.add(tmp);
this.add(tmp);
addIng = false;
}
class MovingButton extends JButton {
double x, y;
double vx, vy;
int count = 0;
E6 parent;
public MovingButton(int x, int y, int width, int height, E6 parent) {
super();
totButton++;
this.setBounds(x, y, width, height);
this.x = x;
this.y = y;
this.parent = parent;
this.setText("0");
double theta = Math.random() * 2 * Math.PI;
vx = Math.sin(theta) * 5;
vy = Math.cos(theta) * 5;
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
double theta = Math.random() * 2 * Math.PI;
vx = Math.sin(theta) * 5;
vy = Math.cos(theta) * 5;
addDouble();
}
});
this.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
addDouble();
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
});
}
void addDouble() {
parent.addDouble();
}
void adjust() {
boolean crash = false;
if (x + vx < 0 || x + vx + this.getWidth() + 20 >= Width) {
vx = -vx;
crash = true;
}
if (y + vy < 0 || y + vy + this.getHeight() + 20 >= Height) {
vy = -vy;
crash = true;
}
x += vx;
y += vy;
if (crash == true) {
count++;
this.setText("" + count);
}
this.setBounds((int) x, (int) y, this.getWidth(), this.getHeight());
}
}
public static void main(String[] args) {
new E6();
}
}
上一篇:[JAVA][作業] 簡易計算機