從網上看了許多有關java多線程的講解,也作筆記總結一下。java
1.實現Runnable接口相比於繼承Thread類:
多線程
(1)適合多個相同的程序代碼的線程去處理同一個資源jvm
(2)能夠避免java中的單繼承的限制ide
(3)代碼能夠被多個線程共享,代碼和數據獨立this
public class Test { public static void main(String[] args) { for(int i=0;i<5;i++){ Thread t = new MThread(); t.start(); } try{ Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } R r = new R(); for(int i=0;i<5;i++){ Thread t = new Thread(r); t.start(); } } } class MThread extends Thread{ public int x = 0; public void run() { System.out.print(++x); } } class R implements Runnable{ private int x = 0; public void run() { System.out.print(++x); } } 執行結果:1111112345
2.main方法也是一個線程。在java中全部的線程都是同時啓動的,而何時哪一個線程先執行,取決於CPU的資源。spa
在java中,每次程序至少啓動2個線程,一個是main線程,一個是垃圾收集線程。由於使用java命令執行一個類時,實際上都會啓動一個JVM,每一個JVM其實就是在操做系統中啓動了一個進程。操作系統
3.線程的強制執行:線程
public class A implements Runnable { public void run() { for(int i=0;i<3;i++){ System.out.println(Thread.currentThread().getName()); } } public static void main(String[] args) { A a = new A(); Thread t = new Thread(a); t.start(); for(int i=0;i<5;i++){ if(i>3){ try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("main thread execute-->"+i); } } } 執行結果:當i>3時,若線程Thread-0爲執行完,則強制執行線程Thread-0 main thread execute-->0 main thread execute-->1 main thread execute-->2 Thread-0 main thread execute-->3 Thread-0 Thread-0 main thread execute-->4
3.線程的中斷code
public class B implements Runnable { public void run() { System.out.println("execute run()"); try{ Thread.sleep(10000); System.out.println("thread finish sleep"); }catch (InterruptedException e){ System.out.println("thread interrupted"); return; } System.out.println("thread end"); } public static void main(String[] args) { B b = new B(); Thread t = new Thread(b); t.start(); try{ Thread.sleep(2000); }catch (InterruptedException e){ e.printStackTrace(); } t.interrupt(); } } 執行結果:execute run() thread interrupted
4.線程的優先級:並不是優先級越高就先執行。誰先執行取決於誰先取得CPU資源。因此setPriority不必定起做用的,在不一樣的操做系統不一樣的jvm上效果也可能不一樣。操做系統也不能保證設置了優先級的線程就必定會先運行或獲得更多的CPU時間。對象
public class C implements Runnable { @Override public void run() { for(int i=0;i<3;i++){ System.out.println(Thread.currentThread().getName()+" execute" + i); } } public static void main(String[] args) { Thread a = new Thread(new C(), "A"); Thread b = new Thread(new C(), "B"); Thread c = new Thread(new C(), "C"); a.setPriority(3); b.setPriority(1); c.setPriority(2); a.start(); b.start(); c.start(); } } 執行結果: C execute0 B execute0 A execute0 B execute1 C execute1 B execute2 A execute1 C execute2 A execute2
5.線程的禮讓:使用yield(),將一個線程的操做暫時交給其餘線程執行
public class D implements Runnable { @Override public void run() { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+" execute "+i); if(i==3){ System.out.println(Thread.currentThread().getName()+" thread 禮讓"); Thread.currentThread().yield(); } } } public static void main(String[] args) { Thread a = new Thread(new D(), "a"); Thread b = new Thread(new D(), "b"); a.start(); b.start(); } } 執行結果:當a線程執行了yield(),若b線程還沒有執行完畢,即交給b線程執行。 b execute 0 a execute 0 b execute 1 a execute 1 b execute 2 a execute 2 b execute 3 a execute 3 b thread 禮讓 a thread 禮讓 b execute 4 a execute 4
6.同步(同步代碼塊和同步方法)
同步代碼塊: public class E implements Runnable { private int count=5; @Override public void run() { for (int i=0;i<10;i++){ synchronized (this){ if(count>0){ try { Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+","+count--); } } } } public static void main(String[] args) { E e = new E(); Thread a = new Thread(e,"a"); Thread b = new Thread(e,"b"); Thread c = new Thread(e,"c"); a.start(); b.start(); c.start(); } } 同步方法: public class E implements Runnable { private int count=5; @Override public void run() { for (int i=0;i<10;i++){ sale(); } } public synchronized void sale(){ if(count>0){ try{ Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+","+count--); } } public static void main(String[] args) { E e = new E(); Thread a = new Thread(e,"a"); Thread b = new Thread(e,"b"); Thread c = new Thread(e,"c"); a.start(); b.start(); c.start(); } } 執行結果:因爲a,b,c三個線程都是用的e對象鎖,因此a執行時,b,c等待 a,5 a,4 a,3 a,2 a,1
7.生產者消費者問題
public class G { public static void main(String[] args) { Info info = new Info(); Producer p = new Producer(info); Consumer c = new Consumer(info); new Thread(p,"p").start(); new Thread(c,"c").start(); } } class Info{ private boolean flag = false; private String name="aa"; private int age = 10; String getName() { return name; } void setName(String name) { this.name = name; } int getAge() { return age; } void setAge(int age) { this.age = age; } public synchronized void set(String name, int age){ if(!flag){ try { super.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name; try{ Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } this.age = age; flag = false; super.notify(); } public synchronized void get(){ if(flag){ try { super.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try{ Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println(this.getName()+"--"+this.getAge()); flag = true; super.notify(); } } class Producer implements Runnable{ private Info info = null; Producer(Info info){ this.info = info; } public void run() { boolean flag = false; for(int i=0;i<5;++i){ if(flag){ this.info.set("aa", 10); flag = false; }else{ this.info.set("zz", 99); flag = true; } } } } class Consumer implements Runnable{ private Info info = null; Consumer(Info info){ this.info = info; } public void run() { for(int i=0;i<5;++i){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.info.get(); } } } 執行結果: aa--10 zz--99 aa--10 zz--99 aa--10