asp.net+Android+IOS開發 、Net培訓、期待與您交流!
(前言:本篇文章主要依據畢向東老師的課程視頻整理而成,如要詳細學習,請觀看畢老師視頻 百度網盤鏈接地址:http://pan.baidu.com/s/1i3m6DrJ)
目錄:1、線程通信--生產消費者示例(線程通信安全、等待喚醒機制) 2、停止線程、及其會出現的問題、及解決的辦法 3、守護線程及幾個Thread的方法 4、工作中線程的常見寫法
1、線程通信--生產消費者示例
代碼示例:
public class PRoducerConsumer {//需求:生產和消費行為依次進行。 設置產品為BMW 設置生產者和消費者線程各兩個 public static void main(String[] args) { Product pro=new Product(); new Thread(new Producter(pro)).start(); new Thread(new Consumer(pro)).start(); new Thread(new Producter(pro)).start(); new Thread(new Consumer(pro)).start(); }}class Product{ private String name; private int No=1; boolean flag=false; public synchronized void set(String names){ while(flag) try { this.wait();//等待狀態 } catch (InterruptedException e) { e.printStackTrace(); } this.name=names+"---"+this.No++; System.out.println(this.name+"---被"+Thread.currentThread().getName()+"生產"); flag=true; this.notifyAll();//喚醒所有線程 } public synchronized void out(){ while(!flag) try { this.wait();//等待狀態 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.name+"---被"+Thread.currentThread().getName()+"消費了-------"); flag=false; this.notifyAll();//喚醒所有線程 }}//生產者class Producter implements Runnable{ private Product p; public Producter(Product pr){ this.p=pr; } public void run(){ while(true){ p.set("BMW"); } } }//消費者class Consumer implements Runnable{ private Product p; public Consumer(Product pr){ this.p=pr; } public void run(){ while(true){ p.out(); } }}
使用JDK5.0新特性改進后的代碼
1 /*JDK5.0后增加了Lock 和Condition新類特性來取代 同步和鎖的繁瑣操作 */ 2 public class ProducerConsumerNew { 3 4 public static void main(String[] args) { 5 6 Product pro=new Product(); 7 8 new Thread(new Producter(pro)).start(); 9 new Thread(new Consumer(pro)).start();10 new Thread(new Producter(pro)).start();11 new Thread(new Consumer(pro)).start();12 13 }14 15 }16 class ProductNew{ 17 private String name;18 private int No=1;19 boolean flag=false;20 21 private Lock lock=new ReentrantLock();22 private Condition con1=lock.newCondition();23 private Condition con2=lock.newCondition();24 25 public void set(String name){26 27 while(flag)28 try {29 lock.lock();30 con1.wait();31 } catch (InterruptedException e) {32 e.printStackTrace();33 }finally{34 lock.unlock();35 }36 this.name=name+"---"+this.No++; 37 System.out.println(this.name+"---被"+Thread.currentThread().getName()+"生產");38 39 this.flag=true;40 con2.signal();41 }42 43 public void out(){ 44 while(!this.flag)45 try {46 lock.lock();47 con2.wait();48 } catch (InterruptedException e) {49 e.printStackTrace();50 }finally{51 lock.unlock();52 con1.signal();53 } 54 System.out.println(this.name+"---被"+Thread.currentThread().getName()+"消費了-------");55 56 this.flag=false;57 }58 }59 //生產者60 class ProducterNew implements Runnable{61 private ProductNew p;62 public ProducterNew(ProductNew pr){63 this.p=pr;64 }65 public void run(){66 while(true){67 p.set("BMW");68 }69 } 70 }71 //消費者72 class ConsumerNew implements Runnable{73 private ProductNew p;74 public ConsumerNew(ProductNew pr){75 this.p=pr;76 } 77 public void run(){78 while(true)79 p.out();80 }81 }
2、停止線程、及其會出現的問題、及解決的辦法
停止線程思路:開啟多線程運行,運行代碼通常是循環結構,只要控制住循環,就可以讓run()方法結束,線程即結束。
特殊情況:當線程處于凍結狀態(wait()),就不會讀取到標記,那么線程就不會結束。
解決辦法:當沒有指定的方式讓凍結的線程恢復到運行狀態時,需要用Interrupt()方法強制清除凍結狀態,再用操作標記讓線程結束
一個簡單的代碼例子
1 public class ThreadStop { 2 3 public static void main(String[] args) { 4 5 ThreadTt tt=new ThreadTt(); 6 7 Thread th1=new Thread(tt); 8 Thread th2=new Thread(tt); 9 th1.start();10 th2.start();11 int count=0;12 while(true){13 if(++count>60){ //循環來控制線程的結束14 th1.interrupt(); //強制清除線程凍結狀態15 th2.interrupt();16 break;17 }18 System.out.println(Thread.currentThread().getName()+"....run---"+count);19 } 20 System.out.println(Thread.currentThread().getName()+"....over");21 }22 }23 class ThreadTt implements Runnable{24 25 boolean flag=true;26 Lock lock=new ReentrantLock();27 Condition con=lock.newCondition();28 public synchronized void run() {29 30 while(flag){31 try {32 wait(); //用這個方法讓線程處于凍結狀態33 } catch (InterruptedException e) {34 System.out.println(e.getStackTrace());35 flag=false;36 }37 System.out.println(Thread.currentThread().getName()+"...run");38 }39 }40 }
3、守護線程及幾個Thread的方法
守護線程/用戶線程:通俗而言為”后臺進程”,當前臺進程都結束時,后臺進程自動結束;當正在運行的線程都是守護線程時,JVM自動退出。
setDaemon()方法設置守護線程,該方法必須在啟動線程前調用
Join()方法 特點:當A線程執行到了B線程的jion()方法是,A就會等待,等B線程都執行完以后,A才會執行。Jion可以用來臨時加入線程執行 線程搶奪cpu執行權
ToString()方法
setPriority()方法 更改線程的優先級,優先級代表搶奪資源的頻率高低
Yield()方法 暫停當前線程的執行,去執行其它線程
4、工作中線程的常見寫法(用到內部類)
不多說,看代碼
1 public class ThreadStand { 2 3 public static void main(String[] args) { 4 //工作中多線程的常見寫法,構建內部類 5 new Thread(){ 6 public void run(){ 7 for(int i=0;i<100;i++) 8 System.out.println(Thread.currentThread().getName()+"....run...."+i); 9 }10 }.start();11 12 for(int i=0;i<100;i++)13 System.out.println(Thread.currentThread().getName()+"....run...."+i);14 15 //構造內部類16 Runnable rn= new Runnable(){17 public void run() {18 for(int i=0;i<100;i++)19 System.out.println(Thread.currentThread().getName()+"....run...."+i); 20 }21 }; 22 new Thread(rn).start(); 23 }24 }
初學者難免錯誤,歡迎評判指教,持續更正ing...........
ASP.Net+Android+IOS開發 、Net培訓、期待與您交流!
新聞熱點
疑難解答