進程是程序在處理機中的一次運行。一個進程既包括其所要執行的指令,也包括了執行指令所需的系統資源,不一樣進程所佔用的系統資源相對獨立。因此進程是重量級的任務,它們之間的通訊和轉換都須要操做系統付出較大的開銷。java
線程是進程中的一個實體,是被系統獨立調度和分派的基本單位。線程本身基本上不擁有系統資源,但它能夠與同屬一個進程的其餘線程共享進程所擁有的所有資源。因此線程是輕量級的任務,它們之間的通訊和轉換隻須要較小的系統開銷。編程
Java支持多線程編程,所以用Java編寫的應用程序能夠同時執行多個任務。Java的多線程機制使用起來很是方便,用戶只需關注程序細節的實現,而不用擔憂後臺的多任務系統。安全
Java語言裏,線程表現爲線程類。Thread線程類封裝了全部須要的線程操做控制。在設計程序時,必須很清晰地區分開線程對象和運行線程,能夠將線程對象看做是運行線程的控制面板。在線程對象裏有不少方法來控制一個線程是否運行,睡眠,掛起或中止。線程類是控制線程行爲的惟一的手段。一旦一個Java程序啓動後,就已經有一個線程在運行。可經過調用Thread.currentThread方法來查看當前運行的是哪個線程。網絡
JAVA中建立線程能夠經過繼承Thread類和實現Runnable接口來建立一個線程。Runnable方式能夠避免Thread 方式因爲JAVA單繼承特性帶來的缺陷。Runnable的代碼能夠被多個線程(Thread實例)共享,適合於多個線程處理同一資源的狀況。多線程
方式一:繼承Threadide
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接口this
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(); } }
場景:一個主線程,一個守護線程,守護線程會在很長一段時間內向本地文件中寫入數據,主線程進入阻塞狀態等待用戶的輸入,一旦確認了用戶的輸入阻塞就會解除掉,主線程繼續運行直到結束,守護線程也會隨虛擬機一同結束。spa
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()); } }
建議使用Runnable這種方式建立線程。 程序中的同一資源指的是同一個Runnable對象。安全的賣票程序中須要加入同步synchronized。操作系統