進程是程序在處理機中的一次運行。一個進程既包括其所要執行的指令,也包括了執行指令所需的系統資源,不一樣進程所佔用的系統資源相對獨立。因此進程是重量級的任務,它們之間的通訊和轉換都須要操做系統付出較大的開銷。github
線程是進程中的一個實體,是被系統獨立調度和分派的基本單位。線程本身基本上不擁有系統資源,但它能夠與同屬一個進程的其餘線程共享進程所擁有的所有資源。因此線程是輕量級的任務,它們之間的通訊和轉換隻須要較小的系統開銷。編程
Java支持多線程編程,所以用Java編寫的應用程序能夠同時執行多個任務。Java的多線程機制使用起來很是方便,用戶只需關注程序細節的實現,而不用擔憂後臺的多任務系統。windows
Java語言裏,線程表現爲線程類。Thread線程類封裝了全部須要的線程操做控制。在設計程序時,必須很清晰地區分開線程對象和運行線程,能夠將線程對象看做是運行線程的控制面板。在線程對象裏有不少方法來控制一個線程是否運行,睡眠,掛起或中止。線程類是控制線程行爲的惟一的手段。一旦一個Java程序啓動後,就已經有一個線程在運行。可經過調用Thread.currentThread方法來查看當前運行的是哪個線程。安全
JAVA中建立線程能夠經過繼承Thread類和實現Runnable接口來建立一個線程。Runnable方式能夠避免Thread 方式因爲JAVA單繼承特性帶來的缺陷。Runnable的代碼能夠被多個線程(Thread實例)共享,適合於多個線程處理同一資源的狀況。網絡
class MyThread extends Thread{ ..... @Override public void run(){ } } MyThread mt=new MyThread(); mt.start();
class MyThread implements Runnable{ .... @Override public void run(){ } } MyThread mt=new MyThread(); Thread td=new Thread(mt); sd.start();
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(); } }
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(); } }
場景:一個主線程,一個守護線程,守護線程會在很長一段時間內向本地文件中寫入數據,主線程進入阻塞狀態等待用戶的輸入,一旦確認了用戶的輸入阻塞就會解除掉,主線程繼續運行直到結束,守護線程也會隨虛擬機一同結束。多線程
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()); } }
測試結果ide
jstack工具到jdk安裝目錄bin文件夾下。jstack能生成JVM當前時刻線程的快照(threaddump, 即當前進程中全部線程的信息)。幫助定位程序問題出現的緣由,如長時間停頓、CPU佔用率太高等。
使用方法
jstack [-l] <pid> : [-l]無關緊要,表示關於鎖的二位信息;<pid>表示進程ID。
建議使用Runnable這種方式建立線程。 程序中的同一資源指的是同一個Runnable對象。安全的賣票程序中須要加入同步synchronized。
如以上文章或連接對你有幫助的話,別忘了在文章結尾處輕輕點擊一下 「還不錯」按鈕或到頁面右下角點擊 「贊一個」 按鈕哦。你也能夠點擊頁面右邊「分享」懸浮按鈕哦,讓更多的人閱讀這篇文章。