1. 程式人生 > >繼承Thread類和實現Runnable介面的對比

繼承Thread類和實現Runnable介面的對比

<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;
		}
	}

}
}

(程式碼有點繁瑣)