一、实验预热
1、写出多线程的声明周期,并解释生命周期中的各个时期。
新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。
运行(running)
线程获得CPU资源正在执行任务(run方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
自然终止:正常运行run方法后终止
异常终止:调用stop方法让一个线程终止运行
2、对于无法返回值的多线程编写,有哪几种实现多线程的方式,写出这些方式之间的区别。
1)继承Thread类,重写run方法。
2)实现Runnable接口,重写run方法,没有返回值,无法上抛异常。
3)实现Callable接口,重写call方法,有返回值,可以上抛异常。
4)使用Executor框架创建线程池。
一般情况下,常见的是第二种和第三种,原因如下:
1)一个类可以实现多个接口,同时还可以继承类,避免单继承带来的局限性。
2)适合资源共享。
二、实验内容
1、编写一个应用程序,除了主线程外,还有两个线程:first和second。first负责模拟一个红色的按钮从坐标(10, 60)运动到(100, 60);second负责模拟一个绿色的按钮从坐标(100, 60)运动到(200, 60)。另外还有一个start按钮,当点击start按钮后,红色按钮平行移动从左边移动到右边,当红色按钮移动到绿色按钮位置后,红色按钮停止在绿色按钮起始位置,然后绿色按钮接着移动。当绿色按钮移动到指定位置后,所有按钮位置重置,然后循环执行上述过程。
代码:
package leif.tests;
import java.awt.Button;
import java.awt.Color;
import java.awt.Component;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class ExperimentalReport {
public static void main(String args[]) {
new MoveButton();
}
}
class MoveButton extends Frame implements Runnable, ActionListener {
private static final long serialVersionUID = 1L;
Thread first, second;
Button redButton, greenButton, startButton;
int distance = 10;
public MoveButton() {
setLayout(null);
setBounds(0, 0, 300, 200);
setVisible(true);
validate();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
first = new Thread(this);
second = new Thread(this);
redButton = new Button();
redButton.setBackground(Color.red);
redButton.setBounds(10, 60, 15, 15);
add(redButton);
greenButton = new Button();
greenButton.setBackground(Color.green);
greenButton.setBounds(100, 60, 15, 15);
add(greenButton);
startButton = new Button("start");
startButton.addActionListener(this);
startButton.setBounds(10, 100, 30, 30);
add(startButton);
}
@Override
public void actionPerformed(ActionEvent e) {
first.start();
second.start();
}
@Override
public void run() {
while (true) {
if (Thread.currentThread() == first) {
moveComponent(redButton);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (Thread.currentThread() == second) {
moveComponent(greenButton);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void moveComponent(Component component) {
if (Thread.currentThread() == first) {
while (distance > 100 && distance <= 200) {
try {
wait();
} catch (Exception exp) {
}
}
distance++;
component.setLocation(distance, 60);
if (distance >= 100) {
component.setLocation(10, 60);
notifyAll();
}
}
if (Thread.currentThread() == second) {
while (distance >= 10 && distance <= 100) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
distance++;
component.setLocation(distance, 60);
if (distance > 200) {
distance = 10;
component.setLocation(100, 60);
notifyAll();
}
}
}
}
结果截图: