黑马程序员--线程【下】
生活随笔
收集整理的這篇文章主要介紹了
黑马程序员--线程【下】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
-------------------?android培訓、java培訓、期待與您交流!------------------
?
?
?/* 線程間通訊: 其實就是多個線程在操作同一個資源, 但是操作的動作不同。 優化! */ class Res { private String name; private String sex; private boolean flag = false;//開始時,沒數據,就false public synchronized void set(String name,String sex) { if(flag) try{this.wait();}catch(Exception e){}//等待 this.name = name; //不同步,中間可能會出現問題 this.sex = sex; flag = true; this.notify();//喚醒 } public synchronized void out() { if(!flag) try{this.wait();}catch(Exception e){} System.out.println(name+"........"+sex); flag = false; this.notify(); } } class Input implements Runnable { private Res r ; Input(Res r) { this.r = r; } public void run() { int x = 0; while(true) { if(x==0) r.set("mike","man"); else r.set("麗麗","女女女女女"); x = (x+1)%2; } } } class Output implements Runnable { private Res r ; Output(Res r) { this.r = r; } public void run() { while(true) { r.out(); } } } class ?InputOutputDemo2 { public static void main(String[] args)? { Res r = new Res(); //簡化:6句2句 new Thread(new Input(r)).start(); new Thread(new Output(r)).start(); /* Input in = new Input(r); Output out = new Output(r); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); */ } } ------------------------------------------------------------------------------------------------------------???
class ProducerConsumerDemo? { 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(); } } /* 對于多個生產者和消費者。 為什么要定義while判斷標記。 原因:讓被喚醒的線程再一次判斷標記。---否則會出現問題:生產一個消費兩次,或者生產兩次消費一次 為什么定義notifyAll, 因為需要喚醒對方線程。 因為只用notify,容易出現只喚醒本方線程的情況。導致程序中的所有線程都等待【死鎖】。 */ class Resource { private String name; private int count = 1; private boolean flag = false; // ?t1 ? ?t2 public synchronized void set(String name) { while(flag)//每次醒來都必須判斷,否則(if)會出現問題:生產兩個,消費一次 try{this.wait();}catch(Exception e){}//t1(放棄資格) ?t2(獲取資格),【用if之判斷一次】醒來之后,不用判斷標記,直接向下執行,導致生產兩個//開發要寫多行,不能寫在一行 this.name = name+"--"+count++; System.out.println(Thread.currentThread().getName()+"...生產者.."+this.name); flag = true; //this.notify();//出現死鎖 this.notifyAll(); } // ?t3 ? t4 ? public synchronized void out() { while(!flag)//每次醒來都必須判斷,否則(if)會出現問題:生產一個消費兩次; try{wait();}catch(Exception e){}//t3(放棄資格) t4(放棄資格) System.out.println(Thread.currentThread().getName()+"...消費者........."+this.name); flag = false; //this.notify();//出現死鎖 this.notifyAll(); } } class Producer implements Runnable { private Resource res; Producer(Resource res) { this.res = res; } public void run() { while(true) { res.set("+商品+"); } } } class Consumer implements Runnable { private Resource res; Consumer(Resource res) { this.res = res; } public void run() { while(true) { res.out(); } } }
------------------------------------------------------------------------------------------------------------????
?
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(); } } /* JDK1.5 中提供了多線程升級解決方案。 將同步Synchronized替換成顯式的Lock操作。 將Object中的wait,notify notifyAll,替換了Condition對象。 該對象可以Lock鎖 進行獲取。 該示例中,實現了本方只喚醒對方操作。 Lock:替代了Synchronized lock? unlock newCondition() Condition:替代了Object wait notify notifyAll await(); signal(); signalAll(); */ class Resource { private String name; private int count = 1; private boolean flag = false; // ?t1 ? ?t2 private Lock lock = new ReentrantLock(); //一個鎖可以有多個condition對象 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,t2//生產者等待 this.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();//消費者等待t3,t4 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) { } } } }------------------------------------------------------------------------------------------------------------?
/* stop方法已經過時。 如何停止線程? 只有一種,run方法結束。 開啟多線程運行,運行代碼通常是循環結構。 只要控制住循環,就可以讓run方法結束,也就是線程結束。 特殊情況: 當線程處于了凍結狀態。 就不會讀取到標記。那么線程就不會結束。 當沒有指定的方式讓凍結的線程恢復到運行狀態時,這時需要對凍結進行清除。 強制讓線程恢復到運行狀態中來。這樣就可以操作標記讓線程結束。 Thread類提供該方法 interrupt();//sleep,wait,join都能被他中斷 */ class StopThread implements Runnable { private boolean flag =true; public ?void run() { while(flag) { /* try { wait(); } catch(InterruptedException e) { System.out.println(Thread.currentThread().getName()+"....run"); } */ System.out.println(Thread.currentThread().getName()+"....run"); } } public void changeFlag()//改變標記方法,控制停止! { flag = false; } } class ?StopThreadDemo { public static void main(String[] args)? { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.setDaemon(true);//在啟動線程前調用守護線程【后臺線程】。//前臺線程結束,后臺線程自動結束 t2.setDaemon(true); t1.start(); t2.start(); int num = 0; while(true) { if(num++ == 60) { //st.changeFlag(); //t1.interrupt();//不該喚醒,喚醒了,會出現異常! //t2.interrupt(); break; } System.out.println(Thread.currentThread().getName()+"......."+num); } System.out.println("over"); } }
------------------------------------------------------------------------------------------------------------??
/* join: 當A線程執行到了B線程的.join()方法時,A就會等待。等B線程都執行完,A才會執行。 join可以用來臨時加入線程執行。 */ class Demo implements Runnable { public void run() { for(int x=0; x<70; x++) { //System.out.println(Thread.currentThread().getName()+"....."+x); System.out.println(Thread.currentThread().toString()+"....."+x); Thread.yield();//暫停現在正在執行的線程,執行其他線程,延緩線程的運行 } } } class ?JoinDemo { public static void main(String[] args) throws Exception { Demo d = new Demo(); Thread t1 = new Thread(d); Thread t2 = new Thread(d); t1.start(); //t1.join();//搶奪cpu執行權,主線程凍結【不會跟t1搶執行權】,t1執行完,主線程恢復執行權 //t1.setPriority(Thread.MAX_PRIORITY);//設置最高優先級 t2.start(); //t1.join();//搶奪cpu執行權,主線程凍結【不會跟t1搶執行權】,---t1和t2交替執行-----t1執行完,主線程恢復執行權,不管t2是否執行完 for(int x=0; x<80; x++) { //System.out.println("main....."+x); } System.out.println("over"); } }
------------------------------------------------------------------------------------------------------------?
//開發的時候可以這么寫! class ThreadTest? { public static void main(String[] args)? { //線程1 new Thread()//匿名內部類//Thread子類對象 { public void run() { for(int x=0; x<100; x++) { System.out.println(Thread.currentThread().getName()+"....."+x); } } }.start(); //線程2【主線程】 for(int x=0; x<100; x++) { System.out.println(Thread.currentThread().getName()+"....."+x); } //線程3 Runnable r ?= new Runnable() { public void run() { for(int x=0; x<100; x++) { System.out.println(Thread.currentThread().getName()+"....."+x); } } }; new Thread(r).start(); //new Test1().start();//用匿名內部類代替外部類 } } /* class Test1 extends Thread { public void run() { for(int x=0; x<100; x++) { System.out.println(Thread.currentThread().getName()+"....."+x); } } } */
轉載于:https://www.cnblogs.com/Stone-sw/archive/2013/03/15/2962331.html
總結
以上是生活随笔為你收集整理的黑马程序员--线程【下】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转载] 中华典故故事(孙刚)——24
- 下一篇: 2440-系统时钟