標籤:java 多線程 thread runnable
Java實現多線程的兩種方式分別是繼承Thread類和實現Runnable介面。
程式碼範例:
class MyThread extends Thread{ private String name; public MyThread(String name){ this.name = name; } @Override public void run(){ for(int i=0;i<7;i++){ System.out.println("線程開始:"+this.name+"次數"+i); } }}
class MyRun implements Runnable{ @Override public void run(){ for(int i=0;i<7;i++){ System.out.println("線程開始:"+Thread.currentThread().getName()+"次數"+i); } }}
public class A{ public static void main(String [] args){ MyThread myThread = new MyThread("myThread"); myThread.start(); MyRun myRun = new MyRun(); Thread run1 = new Thread(myRun, "myRun"); run1.start(); }}
運行結果:
關鍵點1:啟動線程使用start()方法,使用run()方法並不會啟動新線程。
public class A{ public static void main(String [] args){ MyThread myThread1 = new MyThread(); myThread1.run(); MyThread myThread2 = new MyThread(); myThread2.run(); }}
class MyThread extends Thread{ public void run(){ for(int i=0;i<7;i++){ System.out.println("線程:"+Thread.currentThread().getName()+"次數"+i); } }}
start() : 通過調用start0()啟動一個新線程,新線程會執行相應的run()方法。start()不能被重複調用。
run(): run()和普通的成員方法一樣可重複調用。單獨調用run()會在當前線程中執行run(),並不會啟動新線程!
相關源碼:
public synchronized void start() { if (threadStatus != 0) //start()方法不能被重複調用,否則會拋出異常 throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); //加入到線程組中 boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } }}private native void start0();@Overridepublic void run() { if (target != null) { //target是當前的Runnable對象 target.run(); } }
關鍵點2:Thread實現多線程與Runnable實現多線程的區別.1、由於Java使用單繼承,多介面實現原則,所以通過Runnable介面實現多線程更具靈活性;2、Runnable對象可以被多個線程共用,適合於多個線程處理同一資源的情況。(不準確)
賣票問題:
1:Thread
class MyThread extends Thread{ private int tickets =5; @Override public void run() { while (tickets>0) { tickets--; System.out.println(Thread.currentThread().getName()+"賣了一張票,剩餘票數:"+tickets); } }}
public static void main(String [] args){ MyThread myThread1 = new MyThread(); myThread1.start(); MyThread myThread2 = new MyThread(); myThread2.start(); }
MyThread myThread1 = new MyThread();MyThread myThread2 = new MyThread();因為每次都建立了新的MyThread對象,所以最後結果是賣了10張票;
2:Runnable
class MyThread extends Thread{ private int tickets =5; @Override public void run() { while (tickets>0) { tickets--; System.out.println(Thread.currentThread().getName()+"賣了一張票,剩餘票數:"+tickets); } }}
public static void main(String [] args){ MyRunnable r = new MyRunnable(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); }
MyRunnable對象只有一個,多線程共用同一對象,所以賣票結果好像是正確的。
關鍵點3:通過實現Runnable介面共用資源。
class MyRunnable implements Runnable{ private int tickets =10; @Override public void run() { while (tickets>0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } tickets--; System.out.println(Thread.currentThread().getName()+"賣了一張票,剩餘票數:"+tickets); } } }
顯然最後剩餘票數-1和-2是不正確的,所以僅僅實現Runnable介面是無法進行資源共用的,如果需要共用還是需要加入synchronized關鍵字。
class MyRunnable implements Runnable{ private int tickets =10; @Override public void run() { synchronized(this){ while (tickets>0) { tickets--; System.out.println(Thread.currentThread().getName()+"賣了一張票,剩餘票數:"+tickets); } } }}
Java多線程理解