JAVA多線程Thread VS Runnable詳解

來源:互聯網
上載者:User

標籤:

要求
    • 必備知識

      本文要求基本瞭解JAVA編程知識。

    • 開發環境

      windows 7/EditPlus

    • 示範地址

      源檔案

 進程與線程

進程是程式在處理機中的一次運行。一個進程既包括其所要執行的指令,也包括了執行指令所需的系統資源,不同進程所佔用的系統資源相對獨立。所以進程是重量級的任務,它們之間的通訊和轉換都需要作業系統付出較大的開銷。

線程是進程中的一個實體,是被系統獨立調度和指派的基本單位。線程自己基本上不擁有系統資源,但它可以與同屬一個進程的其他線程共用進程所擁有的全部資源。所以線程是輕量級的任務,它們之間的通訊和轉換隻需要較小的系統開銷。

Java支援多線程編程,因此用Java編寫的應用程式可以同時執行多個任務。Java的多線程機制使用起來非常方便,使用者只需關注程式細節的實現,而不用擔心背景多任務系統。

Java語言裡,線程表現為線程類。Thread線程類封裝了所有需要的線程操作控制。在設計程式時,必須很清晰地區分開線程對象和運行線程,可以將線程對象看作是運行線程的控制台。線上程對象裡有很多方法來控制一個線程是否運行,睡眠,掛起或停止。線程類是控制線程行為的唯一的手段。一旦一個Java程式啟動後,就已經有一個線程在運行。可通過調用Thread.currentThread方法來查看當前啟動並執行是哪一個線程。

線程建立的兩種方法

JAVA中建立線程可以通過繼承Thread類和實現Runnable介面來建立一個線程。Runnable方式可以避免Thread 方式由於JAVA單繼承特性帶來的缺陷。Runnable的代碼可以被多個線程(Thread執行個體)共用,適合於多個線程處理同一資源的情況。

  • 繼承Thread類
class MyThread extends Thread{    .....    @Override    public void run(){    }}MyThread mt=new MyThread();mt.start();
  • 實現Runnable介面
class MyThread implements Runnable{    ....    @Override    public void run(){    }}MyThread mt=new MyThread();Thread td=new Thread(mt);sd.start();
Thread&Runnable分別類比賣火車票
  • Thread方式
class MyThread extends Thread{    private int ticketsCont=5; //一共有5張火車票    private String name; //視窗, 也即是線程的名字    public MyThread(String name){        this.name=name;    }    @Override    public void run(){                while(ticketsCont>0){            ticketsCont--; //如果還有票,就賣掉一張票            System.out.println(name+"賣掉了1張票,剩餘票數為:"+ticketsCont);        }            }}public class TicketsThread{    public static void main(String args[]){                //建立三個線程,類比三個視窗賣票        MyThread mt1=new MyThread("視窗1");        MyThread mt2=new MyThread("視窗2");        MyThread mt3=new MyThread("視窗3");        //啟動三個線程,也即是視窗,開始賣票        mt1.start();        mt2.start();        mt3.start();    }}
  • Runnable方式
class MyThread2 implements Runnable{    private int ticketsCont=1000; //一共有5張火車票        @Override    public void run(){                                while(true){                 synchronized(this){                    if(ticketsCont<=0){                        break;                    }                    ticketsCont--; //如果還有票,就賣掉一張票                                        System.out.println(Thread.currentThread().getName()+"賣掉了1張票,剩餘票數為:"+ticketsCont);                                        /*try{                        Thread.sleep(50);  //通過阻塞程式來查看效果                    }                    catch(Exception e){                        System.out.println(e);                    }*/                }            }            }    /*@Override  //不加同步鎖    public void run(){        while(ticketsCont>0){            ticketsCont--; //如果還有票,就賣掉一張票            System.out.println(Thread.currentThread().getName()+"賣掉了1張票,剩餘票數為:"+ticketsCont);        }    }*/}public class TicketsRunnable{    public static void main(String args[]){                MyThread2 mt=new MyThread2();        //建立三個線程來類比三個售票視窗        Thread th1=new Thread(mt,"視窗1");        Thread th2=new Thread(mt,"視窗2");        Thread th3=new Thread(mt,"視窗3");        //啟動三個線程,也即是三個視窗,開始賣票        th1.start();        th2.start();        th3.start();            }}
線程的生命週期

  • 建立:建立一個線程對象,如Thread thd=new Thread()
  • 就緒:建立了線程對象後,調用了線程的start()方法(此時線程知識進入了線程隊列,等待擷取CPU服務 ,具備了啟動並執行條件,但並不一定已經開始運行了)
  • 運行:處於就緒狀態的線程,一旦擷取了CPU資源,便進入到運行狀態,開始執行run()方法裡面的邏輯
  • 終止:線程的run()方法執行完畢,或者線程調用了stop()方法,線程便進入終止狀態
  • 阻塞:一個正在執行的線程在某些情況系,由於某種原因而暫時讓出了CPU資源,暫停了自己的執行,便進入了阻塞狀態,如調用了sleep()方法
線程的分類
  • 使用者線程:運行在前台,執行具有的任務程式的主線程,串連網路的子線程等都是使用者線程
  • 守護線程:運行在後頭,為其他前台線程服務。一旦所有使用者線程都結束運行,守護線程會隨JVM一起結束工作。可以通過調用Thread類的setDaemon(true)方法來設定當前的線程為守護線程,該方法必須在start()方法之前調用,否則會拋出 IllegalThreadStateException異常。在守護線程中產生的新線程也是守護線程。不是所有的任務都可以分配給守護線程來執行,比如讀寫操作或者計算邏輯。
守護線程測試案例

情境:一個主線程,一個守護線程,守護線程會在很長一段時間內向本地檔案中寫入資料,主線程進入阻塞狀態等待使用者的輸入,一旦確認了使用者的輸入阻塞就會解除掉,主線程繼續運行直到結束,守護線程也會隨虛擬機器一同結束。

import java.io.*;import java.util.Scanner;class Daemon  implements Runnable{    @Override    public void run(){        System.out.println("進入守護線程");        try{            writeToFile();        }        catch(Exception e){            e.printStackTrace();        }        System.out.println("退出守護線程");    }    private void writeToFile() throws Exception{            File filename=new File("F:/慕課網(imooc)/細說多線程之Thread VS Runnable/daemon.txt");            OutputStream os=new FileOutputStream(filename,true);            int count=0;            while(count<999){                os.write(("\r\nword"+count).getBytes());                System.out.println("守護線程"+Thread.currentThread().getName()+"向檔案中寫入word"+count++);                Thread.sleep(1000);            }    }}public class DaemonThreadDemo{    public static void main(String args[]){        System.out.println("進入主線程"+Thread.currentThread().getName());        Daemon daemonThread=new Daemon();        Thread thread =new Thread(daemonThread);        thread.setDaemon(true);        thread.start();        Scanner sc=new Scanner(System.in);        sc.next();        System.out.println("退出主線程"+Thread.currentThread().getName());            }}

測試結果

使用jstack產生線程快照

jstack工具到jdk安裝目錄bin檔案夾下。jstack能產生JVM當前時刻線程的快照(threaddump, 即當前進程中所有線程的資訊)。協助定位程式問題出現的原因,如長時間停頓、CPU佔用率過高等。

使用方法

jstack [-l] <pid> : [-l]可有可無,表示關於鎖的二位資訊;<pid>表示進程ID。

總結

建議使用Runnable這種方式建立線程。 程式中的同一資源指的是同一個Runnable對象。安全的賣票程式中需要加入同步synchronized。

如以上文章或連結對你有協助的話,別忘了在文章結尾處輕輕點擊一下 “還不錯”按鈕或到頁面右下角點擊 “贊一個” 按鈕哦。你也可以點擊頁面右邊“分享”懸浮按鈕哦,讓更多的人閱讀這篇文章。

作者:Li-Cheng出處: http://www.cnblogs.com/Li-Cheng/p/4332179.html由於本人水平有限,文章在表述和代碼方面如有不妥之處,歡迎批評指正。留下你的腳印,歡迎評論哦。你也可以關注我,一起學習哦!

JAVA多線程Thread VS Runnable詳解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.