繼承Thread類和實現Runnable介面的對比
阿新 • • 發佈:2019-01-01
<p>1、採用繼承Thread類方法的特點</p><p>優勢:編寫簡單,如果需要訪問當前的執行緒,只需要使用this,並可以在run()方法中呼叫其他執行緒的方法;</p><p>劣勢:執行緒已經繼承了Thread類,不能繼承其他的父類</p><div>
</div>
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;
}
}
}
}
(程式碼有點繁瑣)