開始整理線程以前,以前有個命令忘記整理了,先整理一下jar命令的使用java
其實能夠理解是java的壓縮包
方便使用,只要在classpath設置jar路徑便可
數據庫驅動,ssh框架等都是以jar包體現的數據庫
打包方式一:將指定的class文件打入到jar包中
jar cvf xxx.jar Xxx.class yyy.class併發
打包方式二:將某個目錄下的全部文件打入到jar包中
jar cvf xxx.jar -C xxx/.框架
查看jar文件:
jar -tf xxx.jarssh
運行jar包中的類:
java -cp xxx.jar xx.xx.xx(完整的類名)函數
經常使用的jar命令參數:
c:建立壓縮文件
f:指定存檔名稱
v:顯示詳細信息
m:加入自定義清單this
指定清單文件(xxx.jar/META-INF/MNIFEST.MF)的入口類
jar cvfe classess.jar com.zhaofan.PackagDemo1 classes/.
這樣咱們就能夠經過java -jar xxx.jar直接執行spa
進程:運行時概念,運行的應用程序
線程:應用程序內部併發執行的代碼段,共享內存線程
這裏幾個關鍵詞
yield: 放棄cpu搶佔權
join:等待指定的線程執行完
sleep:靜態方法,讓線程休眠毫秒數
daemo:守護線程code
最簡單的線程代碼:
package study_java.ex9; public class ThreadDemo1 { public static void main(String[] args){ Mythread t1 = new Mythread(); t1.start(); } } class Mythread extends Thread{ public void run(){ while (true){ System.out.println("MyThread"); } } }
join的一個簡單實用例子:
package study_java.ex9; public class ThreadDemo2 { public static void main(String[] args){ Player p1 = new Player("aa",5000); Player p2 = new Player("bb",8000); Player p3 = new Player("cc",2000); Player p4 = new Player("dd",3000); p1.start(); p2.start(); p3.start(); p4.start(); try{ p1.join(); p2.join(); p3.join(); p3.join(); } catch (Exception e){ } System.out.println("人到了,開始玩遊戲"); } } class Player extends Thread{ private String name; private int time; public Player(String name, int time){ this.name = name; this.time = time; } public void run(){ System.out.println("玩家:"+name + "出發了"); try{ Thread.sleep(time); } catch (Exception e){ } System.out.println("玩家:"+name + "到了"); } }
守護線程的一個使用例子
package study_java.ex9; import java.util.Date; public class ThraedDemo3 { public static void main(String[] args){ Room r1 = new Room("no1",15000); Waiter w1 = new Waiter(); //w1.setDaemon(true); 設置守護線程 r1.start(); w1.start(); } } class Room extends Thread{ private String no; private int time; public Room(String no, int time){ this.no = no; this.time = time; } public void run(){ System.out.println("no" + "號房間正在唱歌"); try{ Thread.sleep(time); } catch (Exception e){ } System.out.println("no" + "買單"); } } class Waiter extends Thread{ public Waiter(){ this.setDaemon(true); } public void run(){ while (true){ System.out.println(new java.util.Date()); try{ Thread.sleep(1000); } catch (Exception e){ } } } }
任何一個對象均可以是鎖,信號燈,其實就是一個參照物
一個鎖的代碼例子:
package study_java.ex9; public class ThreadDemo4 { public static void main(String[] args){ Saler s1 = new Saler("a1"); Saler s2 = new Saler("a2"); s1.start(); s2.start(); } } class Saler extends Thread{ // 鎖 static Object lock = new Object(); static int tickts = 100; private String name; public Saler(String name){ this.name = name; } public void run(){ while (true){ int tick = getTickts(); if (tick > 0){ System.out.println(name+":"+ tick); } else { return; } } } // 取票 public int getTickts(){ synchronized (lock){ int currTicket = tickts; tickts --; return currTicket; } } }
還有一種方法是:
public static synchronized int getTickts(){ int currTicket = tickts; tickts --; return currTicket; }
這樣也能實現鎖的機制,可是注意這裏必須是static
咱們整理一個新的寫法,把票池單獨寫出來
public class ThreadDemo2 { public static void main(String[] args){ TicketPool pool = new TicketPool(); Saler s1 = new Saler("s1",pool); Saler s2 = new Saler("s2",pool); s1.start(); s2.start(); } } // 票池 class TicketPool { private int tickets = 100; // 從票池取票 public synchronized int getTickets(){ int ticket = tickets; tickets -= 1; return ticket; } } // 售票員 class Saler extends Thread{ private TicketPool pool = null; private String name; public Saler(String name, TicketPool tp){ this.name = name; this.pool = tp; } public void run(){ while (true){ int no = pool.getTickets(); if (no > 0 ){ System.out.println(name + ":" + no); } else { return; } } } }
兩個小的練習熟悉上面知識點的使用:
車過山洞的問題,山洞同時只容許一個車經過,如今有多輛車,不一樣的車經過的時間不一樣,代碼實現以下:
package study_java.ex11; public class CarCave { public static void main(String[] args){ Cave cave = new Cave(); Car car1 = new Car(cave,10000,"奧迪"); Car car2 = new Car(cave,8000,"奔馳"); Car car3 = new Car(cave,6000,"寶馬"); Car car4 = new Car(cave,2000,"悍馬"); car1.start(); car2.start(); car3.start(); car4.start(); } } class Cave{ public synchronized void crossCar(Car car){ try{ System.out.println(car.name+":開始過山洞了"); Thread.sleep(car.time); System.out.println(car.name+":開始出山洞了"); } catch (Exception e){ } } } class Car extends Thread{ public Cave cave; public int time; public String name; public Car(Cave cave ,int time,String name){ this.cave = cave; this.time = time; this.name = name; } public void run(){ cave.crossCar(this); } }
第二個小練習是咱們常常遇到的場景,取票問題,如今有一個取票機,可是有五十我的要取票,實現代碼以下:
package study_java.ex11; public class TicketDemo1 { public static void main(String[] args){ TicketMachine m = new TicketMachine(); for (int i=0;i<50;i++){ new Person(m,"tom"+i).start(); } } } // 取票機 class TicketMachine{ private int ticketNo = 1; // 打印票號 public synchronized int printTicktNo(){ int currTicketNo = ticketNo; ticketNo ++; return currTicketNo; } } class Person extends Thread{ private TicketMachine m; private String name; public Person(TicketMachine m,String name) { this.m = m; this.name = name; } public void run(){ int no = m.printTicktNo(); System.out.println(name+ ":" + no); } }
經過上面的知識點,寫一個生產者好消費者模型
package study_java.ex11; import java.util.LinkedList; import java.util.List; public class PCDemo1 { public static void main(String[] args){ MyList myList = new MyList(); Productor p = new Productor(myList); Consumer c = new Consumer(myList); Consumer c2 = new Consumer(myList); Consumer c3 = new Consumer(myList); p.start(); c.start(); c2.start(); c3.start(); } } class MyList{ private int Max = 100; private List<Integer> list = new LinkedList<Integer>(); public void addLast(Integer i){ while (true){ synchronized (list){ if (list.size() < Max){ list.add(i); return; } } } } public Integer removeFirst(){ while (true){ synchronized (list){ if(!list.isEmpty()){ return list.remove(0); } } } } } class Productor extends Thread{ private MyList myList; public Productor(MyList myList){ this.myList = myList; } public void run(){ int i = 1; while (true){ myList.addLast(new Integer(i)); System.out.println("生產者生產了"+i+"號"); i++; } } } class Consumer extends Thread{ private MyList myList; public Consumer(MyList myList){ this.myList = myList; } public void run(){ while (true){ int no = myList.removeFirst(); System.out.println("消費者消費了"+no+"號"); } } }
生產者消費者而改進版本:
package study_java.ex11; import java.util.LinkedList; import java.util.List; public class PCDemo5 { public static void main(String[] args){ Pool pool = new Pool(); Producter p1 = new Producter(pool); Consumer c1 = new Consumer(pool); p1.start(); c1.start(); } } class Pool{ private List<Integer> list = new LinkedList<Integer>(); private int Max = 100; public void addLast(int n){ synchronized (this){ while (list.size() >= Max){ try{ this.wait(); } catch (Exception e){ e.printStackTrace(); } } list.add(new Integer(n)); this.notifyAll(); } } public int remove(){ synchronized (this){ while (list.size() == 0){ try{ this.wait(); } catch (Exception e){ e.printStackTrace(); } } int no = list.remove(0); this.notifyAll(); return no; } } } // 生產者 class Producter extends Thread{ private Pool pool; static int i = 1; public Producter(Pool pool){ this.pool = pool; } public void run(){ while (true){ pool.addLast(i++); System.out.println("生產者生產了"+i+"號"); } } } // 消費者 class Consumer extends Thread{ private Pool pool; public Consumer(Pool pool){ this.pool = pool; } public void run(){ while (true){ int no = pool.remove(); System.out.println("消費者消費了"+no+"號"); } } }
wait():讓當前線程進入到鎖對象的等待隊列裏,同時釋放鎖旗標。這個方法是當前鎖對象的方法
wait這裏還能夠添加參數wait(int n) :等待指定的時間片,等待隊列中的線程最多等待n毫秒
notify():這個方法是當前鎖對象的方法,注意這裏並不會釋放鎖
notifyAll():通知等待隊列中的全部線程均可以搶佔cpu運行,通知須要得到對象的監控權
sleep:當前CPU的搶佔權,和鎖對象的監控權無關。
Thread.currentThread().getName():獲取當前線程名字
Thread.currentThread().setName():設置當前線程名字
priority:1-10從低到高,默認是5
Thread.currentThread().getPriority():設置當前線程優先級
線程狀態:
BLOCKED: 阻塞
NEW:新建
RUNNABL:執行
TERMINATED:已經終止
TIMED_WAITING:限時等待
WAITING:等待
建立一個線程的另一種方式:
實現Runnable接口
1. 子類覆蓋接口中的run方法
2. 經過Thread類建立線程,並將實現了Runnable接口的子類對象做爲參數傳遞給Thread類的構造函數
3. Thread類對象調用start方法開啓線程
代碼例子以下:
package study_java.ex11; public class RunnableDemo1 { public static void main(String[] args){ MyRunnabl m = new MyRunnabl(); new Thread(m).start(); } } class MyRunnabl implements Runnable{ public void run(){ System.out.println("hello world"); } }
synchronized(對象)
{
須要同步的代碼
}
同步的特色:
同步的前提是:
須要兩個或者兩個以上的線程
多個線程使用的同一個鎖
同步的弊端:當線程至關多時,由於每一個線程都會去判斷同步上的鎖,這是很耗費資源的,無形中會下降程序的額運行效率