黑马程序员5 多线程
------- android培訓、java培訓、期待與您交流! ----------
創建線程的第一種方式:繼承Thread類。
步驟:
1,定義類繼承Thread。
2,復寫Thread類中的run方法。
目的:將自定義代碼存儲在run方法。讓線程運行。
3,調用線程的start方法,
該方法兩個作用:啟動線程,調用run方法。
創建線程的第二種方式:實現Runable接口
步驟:
1,定義類實現Runnable接口
2,覆蓋Runnable接口中的run方法。
將線程要運行的代碼存放在該run方法中。
3,通過Thread類建立線程對象。
4,將Runnable接口的子類對象作為實際參數傳遞給Thread類的構造函數。
為什么要將Runnable接口的子類對象傳遞給Thread的構造函數。
因為,自定義的run方法所屬的對象是Runnable接口的子類對象。
所以要讓線程去指定指定對象的run方法。就必須明確該run方法所屬對象。
5,調用Thread類的start方法開啟線程并調用Runnable接口子類的run方法。
實現方式和繼承方式有什么區別呢?
實現方式好處:避免了單繼承的局限性。
在定義線程時,建立使用實現方式。
兩種方式區別:
繼承Thread:線程代碼存放Thread子類run方法中。
實現Runnable,線程代碼存在接口的子類的run方法。
范例:
public class Test1 {public static void main(String[] args) {for(int i=0;i<3;i++){new Thread(new Mess()).start();}} }class Mess implements Runnable{private static int taskcount = 0;private final int id = taskcount ++;Mess(){System.out.println("new message"+id);}@Overridepublic void run() {System.out.println("r1:"+id);Thread.yield(); //對線程調度器的一種建議System.out.println("r2:"+id);Thread.yield();System.out.println("r3:"+id);Thread.yield();System.out.println("end"+id);} }
=========================================================
Java對于多線程的安全問題提供了專業的解決方式。
就是同步代碼塊。
synchronized(對象)
{
需要被同步的代碼
}
對象如同鎖。持有鎖的線程可以在同步中執行。
沒有持有鎖的線程即使獲取cpu的執行權,也進不去,因為沒有獲取鎖。
同步規則(何時使用同步):如果正在寫一個變量,他可能接下來被另一個線程讀取,或者正在讀取一個上一次已經被另一個線程寫過的變量,必須使用同步,并且,讀寫線程都必須用相同的監視器鎖同步。
同步函數的鎖是this
靜態同步函數的鎖是Class對象。
?
public class Test1 {public static void main(String[] args) {for(int i=0;i<3;i++){new Thread(new Mess()).start();}} }class Mess implements Runnable{private static int taskcount = 0;private final int id = taskcount ++;Mess(){System.out.println("new message"+id);}@Overridepublic void run() {System.out.println("r1:"+id);Thread.yield(); //對線程調度器的一種建議System.out.println("r2:"+id);Thread.yield();System.out.println("r3:"+id);Thread.yield();System.out.println("end"+id);} }
=======================================================
等待/喚醒機制
涉及的方法:
1.wait():讓線程處于凍結狀態,被wait的線程會被存儲到線程池中。
2.notify():喚醒線程池中的一個線程(任意)。
3.notifyAll():喚醒線程池中的所有線程。
這些方法都必須定義在同步中,因為這些方法是用于操作線程狀態的方法,
必須要明確到底操作的是哪個鎖上的線程。
為什么操作線程的方法 wait、notify、notifyAll定義在了Object類中?
因為這些方法是監視器的方法,監視器其實就是鎖。
鎖可以是任意的對象,任意的對象調用的方法一定定義在Object類中。
========================================================
Lock接口
將同步和鎖封裝成了對象,并將操作鎖的方式定義到了該對象中,將隱式動作變成了顯式動作。
Lock lock=new ReentrantLock();
lock.lock();//獲取鎖
code...;//throw Exception();
lock.unlock();//釋放鎖
try
{
lock.lock();//獲取鎖
}
finally
{
lock.unlock;//釋放鎖
}
Lock接口:它的出現替代了同步代碼塊或者同步函數。將同步的隱式鎖操作變成了顯式鎖操作;
同時更為靈活,可以一個鎖上加上多組監視器。
lock();獲取鎖
unlock();釋放鎖,通常需要定義到finally代碼塊中。
Condition接口:它的出現替代了Object中的wait、notify、notifyAll方法。
將這些監視器方法單獨進行了封裝,變成了Condition監視器對象,
可以和任意鎖組合。
await();//等待
signal();//喚醒一個等待線程
signalAll();//喚醒所有等待線程
import java.util.concurrent.locks.*;class ProducerConsumerDemo2 {public static void main(String[] args) {Resource r = new Resource();Producer pro = new Producer(r);Consumer con = new Consumer(r);Thread t1 = new Thread(pro);Thread t2 = new Thread(pro);Thread t3 = new Thread(con);Thread t4 = new Thread(con);t1.start();t2.start();t3.start();t4.start();} } class Resource {private String name;private int count = 1;private boolean flag = false;// t1 t2private Lock lock = new ReentrantLock();private Condition condition_pro = lock.newCondition();private Condition condition_con = lock.newCondition();public void set(String name)throws InterruptedException{lock.lock();try{while(flag)condition_pro.await();//t1,t2this.name = name+"--"+count++;System.out.println(Thread.currentThread().getName()+"...生產者.."+this.name);flag = true;condition_con.signal();}finally{lock.unlock();//釋放鎖的動作一定要執行。 }}// t3 t4 public void out()throws InterruptedException{lock.lock();try{while(!flag)condition_con.await();System.out.println(Thread.currentThread().getName()+"...消費者........."+this.name);flag = false;condition_pro.signal();}finally{lock.unlock();}} }class Producer implements Runnable {private Resource res;Producer(Resource res){this.res = res;}public void run(){while(true){try{res.set("+商品+");}catch (InterruptedException e){}}} }class Consumer implements Runnable {private Resource res;Consumer(Resource res){this.res = res;}public void run(){while(true){try{res.out();}catch (InterruptedException e){}}} }
===============================================================================
interrupt() 將處于強制凍結狀態的線程,恢復到運行狀態并處理InterruptedException
public class InterruptDemo {public static void main(String[] args) {Thread t = new Thread(new Demo());t.start();System.out.println("Start");t.interrupt();} }class Demo implements Runnable{private boolean flag = true;@Overridepublic synchronized void run() {while(flag){try {wait();} catch (InterruptedException e) {System.out.println("interrupted");flag = false;//通過修改標志位,讓線程停止 }}System.out.println("end");} }
=======================================================?
守護線程: t1.setDaemon(true);
t1.start();
將線程聲明為守護線程。(當前臺線程停止時,守護線程強行停止)
join:
當A線程執行到了B線程的.join()方法時,A就會等待。等B線程都執行完,A才會執行。
join可以用來臨時加入線程執行。
class Demo2 implements Runnable {public void run(){for(int x=0; x<70; x++){System.out.println(Thread.currentThread().toString()+"....."+x);Thread.yield();}} }public class JoinDemo {public static void main(String[] args) throws Exception{Demo2 d = new Demo2();Thread t1 = new Thread(d);t1.start();t1.join();for(int x=0; x<40; x++){System.out.println("main....."+x);}System.out.println("over");} }
優先級:setPriority(Thread.MAX_PRIORITY);//設置到最高優先級
線程組:每個線程屬于其創建者所在的線程組。調用線程的toString方法可以看到其線程組。
?
轉載于:https://www.cnblogs.com/grjelf/archive/2012/10/19/2726502.html
總結
以上是生活随笔為你收集整理的黑马程序员5 多线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 跪求鬼刀图片要4k高清无水印的,最好百度
- 下一篇: asp.net 防注入