1、采用继承Thread类方法的特点
优势:编写简单,如果需要访问当前的线程,只需要使用this,并可以在run()方法中调用其他线程的方法;
劣势:线程已经继承了Thread类,不能继承其他的父类
package test02;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MoveButtonWindow extends JFrame implements ActionListener{
private JButton startButton;
private JButton stopButton;
private JButton exitButton;
private JButton rightButton;
private JButton leftButton;
MoveToRight right;
MoveToLeft left;
//构造方法
public MoveButtonWindow(){
//设置窗口标题
setTitle("线程测试");
//创建面板
JPanel centerPanel=new JPanel();
JPanel controlPanel=new JPanel();
add(centerPanel,BorderLayout.CENTER);
add(controlPanel,BorderLayout.SOUTH);
//创建按钮
startButton =new JButton("开始");
this.startButton.addActionListener(this);
stopButton=new JButton("停止");
this.stopButton.addActionListener(this);
exitButton=new JButton("退出");
this.exitButton.addActionListener(this);
controlPanel.add(startButton);
controlPanel.add(exitButton);
controlPanel.add(stopButton);
//定义centerPanel的布局,并添加按钮组件
//分别创建两个能够移动的按钮
centerPanel.setLayout(null);
centerPanel.setBackground(Color.black);
rightButton=new JButton("向右移动");
rightButton.setBackground(Color.yellow);
rightButton.setBounds(0, 5, 100, 30);
leftButton=new JButton("向左移动");
leftButton.setBackground(Color.red);
leftButton.setBounds(395, 90, 100, 30);
centerPanel.add(leftButton);
centerPanel.add(rightButton);
//新建控制按钮移动的线程right和left,处于新建状态
right=new MoveToRight(rightButton);
left=new MoveToLeft(leftButton);
//设置窗口的一些属性
setBounds(100,100,500,200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
setVisible(true);
validate();
/*验证这个容器和它的所有子组件。
验证一个容器意味着布局它的子组件。
布置相关的变化,比如设置组件的边界,或者将一个组件添加到容器,容器会自动失效。
注意容器的祖先也可能无效(见组件。无效细节。)因此,恢复层次结构的有效性,
validate()方法应该调用层次结构的最顶层无效的容器。*/
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource()==this.startButton){
//如果线程right死亡了,则重新给线程分配实体
if(!right.isAlive()){
right=new MoveToRight(rightButton);
}
//如果线程left死亡了,则重新给线程分配实体'
if(!left.isAlive()){
left=new MoveToLeft(leftButton);
}
right.start();
left.start();
}
//如果点击通知按钮则结束线程
else if(e.getSource()==this.stopButton){
right.setBoo(false);
left.setBoo(false);
}
//如果点击退出则退出应用程序
else if(e.getSource()==this.exitButton){
right.setBoo(false);
left.setBoo(false);
System.exit(0);
}
}
public static void main(String[] args){
new MoveButtonWindow();
}
}
package test02;
import javax.swing.JButton;
public class MoveToLeft extends Thread{
private JButton button;
boolean boo=true;
public MoveToLeft(JButton button){
this.button=button;
}
public void run(){
while(true){
int x=button.getBounds().x;
x=x-5;
if(x>400){
x=5;
}
button.setLocation(x,90);
try{
//调用sleep方法让线程暂停0.2秒
Thread.sleep(200);
} catch (InterruptedException e){
e.printStackTrace();
}
//结束当前线程
if(!boo){
return;
}
}
}
public boolean isBoo(){
return boo;
}
public void setBoo(boolean boo){
this.boo=boo;
}
}
package test02;
import java.io.IOException;
import javax.swing.JButton;
public class MoveToRight extends Thread{
private JButton button;
boolean boo=true;
public MoveToRight(JButton button){
this.button=button;
}
public void run(){
while(true){
int x=button.getBounds().x;
x=x+5;
if(x>400){
x=5;
}
button.setLocation(x,5);
try{
//调用sleep方法让线程暂停0.2秒
Thread.sleep(100);
} catch (InterruptedException e){
e.printStackTrace();
}
//结束当前线程
if(!boo){
return;
}
}
}
public boolean isBoo(){
return boo;
}
public void setBoo(boolean boo){
this.boo=boo;
}
}
2、采用实现Runnable方法的特点
优势:实现了Runnable接口的类,还可以extends 其他的类,多个线程共享一个target对象,适合多线程用来处理同一份资源;
劣势:编程访问线程时,需要调用Thread.currentThread()方法
package test03;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MoveButtonWindow extends JFrame implements ActionListener,Runnable{
private JButton startButton;
private JButton stopButton;
private JButton exitButton;
private JButton rightButton;
private JButton leftButton;
Thread right;
Thread left;
boolean boo =true;
public MoveButtonWindow(){
setTitle("线程测试");
JPanel centerPanel=new JPanel();
JPanel controlPanel=new JPanel();
add(centerPanel,BorderLayout.CENTER);
add(controlPanel,BorderLayout.SOUTH);
startButton=new JButton("开始");
startButton.addActionListener(this);
stopButton=new JButton("停止");
stopButton.addActionListener(this);
exitButton=new JButton("退出");
exitButton.addActionListener(this);
controlPanel.add(this.startButton);
controlPanel.add(this.stopButton);
controlPanel.add(this.exitButton);
rightButton=new JButton("向右移动");
leftButton=new JButton("向左移动");
centerPanel.add(rightButton);
centerPanel.add(leftButton);
//创建线程right和left,当前窗口的对象为target,线程处于新建状态
right=new Thread(this);
left=new Thread(this);
//设置窗口的一些属性
setBounds(100,100,500,200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
setVisible(true);
validate();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new MoveButtonWindow();
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==this.startButton){
if(!right.isAlive()){
right=new Thread(this);
}
if(!left.isAlive()){
left=new Thread(this);
}
//设置标标记变量为true;
boo=true;
right.start();
left.start();
}
else if(e.getSource()==this.stopButton){
boo=false;
}
else if(e.getSource()==this.exitButton){
boo=false;
System.exit(0);
}
}
@Override
public void run() {
// TODO Auto-generated method stub
//判断当前线程是right线程
while(true){
if(Thread.currentThread()==right)
{
int x=this.rightButton.getBounds().x;
x=x+6;
if(x>400){
x=6;
}
rightButton.setLocation(x,5);
try{
Thread.sleep(100);
}
catch(InterruptedException e){
e.printStackTrace();
}
}
else if(Thread.currentThread()==left){
int x=this.leftButton.getBounds().x;
x=x-6;
if(x<20){
x=395;
}
leftButton.setLocation(x,90);
try{
Thread.sleep(100);
}
catch(InterruptedException e){
e.printStackTrace();
}
}
//如果线程boo为false,则结束进程,线程进入死亡状态
if(!boo){
return;
}
}
}
}