1.1、線程之間的通信方法
多個線程在處理統一資源,但是任務卻不同,這時候就需要線程間通信。
等待/喚醒機制涉及的方法:
1. wait():讓線程處于凍結狀態,被wait的線程會被存儲到線程池中。
2. notify():喚醒線程池中的一個線程(任何一個都有可能)。
3. notifyAll():喚醒線程池中的所有線程。
備注
1、這些方法都必須定義在同步中,因為這些方法是用于操作線程狀態的方法。
2、必須要明確到底操作的是哪個鎖上的線程!
3、wait和sleep區別?
1)wait可以指定時間也可以不指定。sleep必須指定時間。
2)在同步中時,對CPU的執行權和鎖的處理不同。
wait:釋放執行權,釋放鎖。
sleep:釋放執行權,不釋放鎖。
為什么操作線程的方法wait、notify、notifyAll定義在了object類中,因為這些方法是監視器的方法,監視器其實就是鎖。
鎖可以是任意的對象,任意的對象調用的方式一定在object類中。
1.2、兩個線程交替打印1-100
package com.pb.thread.demo1;public class Demo { PRivate int num=1; /* * 打印偶數 */ public synchronized void put(){ if(num%2==0){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } notify(); System.out.println(Thread.currentThread().getName()+","+num); num++; } /* * 打印奇數 */ public synchronized void get(){ if(num%2!=0){ try { //當前線程等待 wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //喚醒另一等待中的線程 notify(); System.out.println(Thread.currentThread().getName()+","+num); num++; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } }
package com.pb.thread.demo1;/** * 打印偶數 * @author denny * */public class A implements Runnable { Demo demo; public A(Demo demo){ this.demo=demo; } @Override public void run() { while(demo.getNum()<100){ demo.put(); } }}package com.pb.thread.demo1;/** * 打印奇數 * @author denny * */public class B implements Runnable { Demo demo; public B(Demo demo) { this.demo = demo; } @Override public void run() { while(demo.getNum()<100){ demo.get(); } }}
測試類
package com.pb.thread.demo1;/** * 2個線程交替打印1-100 * @author denny * */public class Test { public static void main(String[] args) { Demo demo=new Demo(); A a=new A(demo); B b=new B(demo); Thread t1=new Thread(a); Thread t2=new Thread(b); t1.start(); t2.start(); }}
結果:
Picked up java_TOOL_OPTIONS: -javaagent:/usr/share/java/jayatanaag.jar Thread-0,1Thread-1,2Thread-0,3Thread-1,4Thread-0,5Thread-1,6Thread-0,7Thread-1,8Thread-0,9Thread-1,10Thread-0,11Thread-1,12Thread-0,13Thread-1,14Thread-0,15Thread-1,16Thread-0,17Thread-1,18Thread-0,19Thread-1,20Thread-0,21Thread-1,22Thread-0,23Thread-1,24Thread-0,25Thread-1,26Thread-0,27Thread-1,28Thread-0,29Thread-1,30Thread-0,31Thread-1,32Thread-0,33Thread-1,34Thread-0,35Thread-1,36Thread-0,37Thread-1,38Thread-0,39Thread-1,40Thread-0,41Thread-1,42Thread-0,43Thread-1,44Thread-0,45Thread-1,46Thread-0,47Thread-1,48Thread-0,49Thread-1,50Thread-0,51Thread-1,52Thread-0,53Thread-1,54Thread-0,55Thread-1,56Thread-0,57Thread-1,58Thread-0,59Thread-1,60Thread-0,61Thread-1,62Thread-0,63Thread-1,64Thread-0,65Thread-1,66Thread-0,67Thread-1,68Thread-0,69Thread-1,70Thread-0,71Thread-1,72Thread-0,73Thread-1,74Thread-0,75Thread-1,76Thread-0,77Thread-1,78Thread-0,79Thread-1,80Thread-0,81Thread-1,82Thread-0,83Thread-1,84Thread-0,85Thread-1,86Thread-0,87Thread-1,88Thread-0,89Thread-1,90Thread-0,91Thread-1,92Thread-0,93Thread-1,94Thread-0,95Thread-1,96Thread-0,97Thread-1,98Thread-0,99Thread-1,100
交替打印
一個輸入,一個輸出
package com.pb.thread.demo3;/** * * @author Denny * 線程間通訊: * 其它就是多個線程在操作同一個資源 * 只是操作的動作不同 * */public class Person { private String name; private int age; private String gender; private boolean flag=false; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public boolean getFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } }//======================package com.pb.thread.demo3;public class Input implements Runnable { private Person person; public Input(Person person) { this.person = person; } @Override public void run() { int x = 0; while (true) { synchronized (person) { if (person.getFlag()) { try { person.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (x == 0) { person.setName("jony"); person.setAge(33); person.setGender("man"); } else { person.setName("李麗"); person.setAge(23); person.setGender("女"); } x = (x + 1) % 2; person.setFlag(true); person.notify(); } } } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; }}//=======================package com.pb.thread.demo3;public class Output implements Runnable { private Person person; public Output(Person person) { this.person = person; } @Override public void run() { while (true) { synchronized (person) { if (!(person.getFlag())) { try { person.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("姓名:" + person.getName() + "年齡:" + person.getAge() + ",性別:" + person.getGender()); person.setFlag(false); person.notify(); } } } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; }}//====================package com.pb.thread.demo3;/** * * @author Denny *wait(),notify(),notifyAll() *都使用在同步中,因為要對持胡監視器(鎖)的線程操作 *因為只有同步才有鎖 *為什么這些操作線程的方法要定義在Object類中呢? *國為這些方法在操作線程時,都必須要標識它們所操作作線程只有的鎖 *只有同一個鎖上的被等待,可以被同一個鎖上的notify()喚醒 *不可以對不同鎖中的線程喚醒 *等待和喚醒必須是同一個鎖。 *鎖可以是任意對象,可以被任意對象調用的方法在Object中. */public class Test { public static void main(String[] args) { Person person=new Person(); Input input=new Input(person); Output output = new Output(person); Thread t1=new Thread(input); Thread t2=new Thread(output); t1.start(); t2.start(); }}
優化以上代碼
package com.pb.thread.demo3;/** * * @author Denny * 線程間通訊: * 其它就是多個線程在操作同一個資源 * 只是操作的動作不同 * */public class Person { private String name; private int age; private String gender; private boolean flag; public synchronized void setThis(String name,int age,String gender){ if(flag){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name=name; this.age=age; this.gender=gender; this.flag=true; notify(); } public synchronized void getThis(){ if(!flag){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("姓名:" + this.name + "年齡:" + this.age + ",性別:" + this.gender); this.flag=false; notify(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public boolean getFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } }//====================package com.pb.thread.demo3;public class Input implements Runnable { private Person person; public Input(Person person) { this.person = person; } @Override public void run() { int x = 0; while (true) { if (x == 0) { person.setThis("jony", 33,"man"); } else { person.setThis("李麗", 23,"女"); } x = (x + 1) % 2; } } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; }}//========================package com.pb.thread.demo3;public class Output implements Runnable { private Person person; public Output(Person person) { this.person = person; } @Override public void run() { while (true) { person.getThis(); } } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; }}//=================package com.pb.thread.demo3;/** * * @author Denny *wait(),notify(),notifyAll() *都使用在同步中,因為要對持胡監視器(鎖)的線程操作 *因為只有同步才有鎖 *為什么這些操作線程的方法要定義在Object類中呢? *國為這些方法在操作線程時,都必須要標識它們所操作作線程只有的鎖 *只有同一個鎖上的被等待,可以被同一個鎖上的notify()喚醒 *不可以對不同鎖中的線程喚醒 *等待和喚醒必須是同一個鎖。 *鎖可以是任意對象,可以被任意對象調用的方法在Object中. */public class Test { public static void main(String[] args) { Person person=new Person(); new Thread(new Input(person)).start(); new Thread(new Output(person)).start(); /* Input input=new Input(person); Output output = new Output(person); Thread t1=new Thread(input); Thread t2=new Thread(output); t1.start(); t2.start();*/ }}
姓名:李麗年齡:23,性別:女姓名:jony年齡:33,性別:man姓名:李麗年齡:23,性別:女姓名:jony年齡:33,性別:man姓名:李麗年齡:23,性別:女姓名:jony年齡:33,性別:man
2.1、單個生產者和單個消費者
package com.pb.thread.demo4;public class Product { private String name; private int count; private boolean flag; //生產 public synchronized void set(String name){ if(flag){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name=name+"..."+count++; System.out.println(Thread.currentThread().getName()+"---生產者---"+this.name); this.flag=true; notify(); } public synchronized void get(){ if(!flag){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"--------消費者------------"+name); this.flag=false; notify(); }}//======================package com.pb.thread.demo4;public class Producter implements Runnable { private Product product; public Producter(Product product){ this.product=product; } @Override public void run() { while(true){ product.set("產品"); } }}//================package com.pb.thread.demo4;public class Consumer implements Runnable { private Product product; public Consumer(Product product){ this.product=product; } @Override public void run() { while(true){ product.get(); } }}//================package com.pb.thread.demo4;public class Test { public static void main(String[] args) { Product p=new Product(); Producter producter=new Producter(p); Consumer consumer=new Consumer(p); Thread t1=new Thread(producter); Thread t2=new Thread(consumer); t1.start(); t2.start(); }}
結果:
Thread-0---生產者---產品...20901Thread-1--------消費者------------產品...20901Thread-0---生產者---產品...20902Thread-1--------消費者------------產品...20902Thread-0---生產者---產品...20903Thread-1--------消費者------------產品...20903Thread-0---生產者---產品...20904Thread-1--------消費者------------產品...20904Thread-0---生產者---產品...20905Thread-1--------消費者------------產品...20905Thread-0---生產者---產品...20906Thread-1--------消費者------------產品...20906Thread-0---生產者---產品...20907Thread-1--------消費者------------產品...20907Thread-0---生產者---產品...20908Thread-1--------消費者------------產品...20908
2.2、多個生產者和多個消費者
package com.pb.thread.demo4;public class Product { private String name; private int count; private boolean flag; //生產 public synchronized void set(String name){ while(flag){ //修改為循環判斷 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name=name+"..."+count++; System.out.println(Thread.currentThread().getName()+"---生產者---"+this.name); this.flag=true; notifyAll(); //修改為notifyAll(); } public synchronized void get(){ while(!flag){//修改為循環判斷 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"--------消費者------------"+name); this.flag=false; notifyAll();//修改為notifyAll(); }}
一、Lock
Lock
實現提供了比使用 synchronized
方法和語句可獲得的更廣泛的鎖定操作。此實現允許更靈活的結構,可以具有差別很大的屬性,可以支持多個相關的 Condition
對象。
public interface Condition
Condition
將 Object
監視器方法(wait
、notify
和 notifyAll
)分解成截然不同的對象,以便通過將這些對象與任意 Lock
實現組合使用,為每個對象提供多個等待 set(wait-set)。其中,Lock
替代了 synchronized
方法和語句的使用,Condition
替代了 Object 監視器方法的使用。
package com.pb.thread.demo4;import java.util.concurrent.locks.*;public class Product { private String name; private int count; private boolean flag; Lock lock = new ReentrantLock();// 聲明鎖對象 // 聲明2個condition對象來表示生產者和消費都,如果有多個可以聲明多個 // 顯示聲明 Condition condition_pro = lock.newCondition();// 生產者 Condition condition_con = lock.newCondition(); // 生產 public void set(String name) { // 加鎖 lock.lock(); try { while (flag) { // 修改為循環判斷 condition_pro.await(); // 指定對象鎖睡覺 } this.name = name + "..." + count++; System.out.println(Thread.currentThread().getName() + "---生產者---" + this.name); this.flag = true; // 喚醒指定線程鎖 condition_con.signal();// 喚醒消費都線程 } catch (InterruptedException e) { e.printStackTrace(); } finally { // 釋放鎖 lock.unlock(); } } public void get() { // 加鎖 lock.lock(); try { while (!flag) { //消費對象鎖上 condition_con.await(); } System.out.println(Thread.currentThread().getName() + "--------消費者------------" + name); this.flag = false; //喚醒生產者 condition_pro.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { //釋放鎖 lock.unlock(); } }}
4.1、線程常用方法
No. | 方法名稱 | 類型 | 描述 |
1 | public Thread(Runnable target) | 構造 | 接收Runnable接口子類對象,實例化Thread對象 |
2 | public Thread(Runnable target,String name) | 構造 | 接收Runnable接口子類對象,實例化Thread對象,并設置線程名稱 |
3 | public Thread(String name) | 構造 | 實例化Thread對象,并設置線程名稱 |
4 | public static Thread currentThread() | 普通 | 返回目前正在執行的線程 |
5 | public final String getName() | 普通 | 返回線程的名稱 |
6 | public final int getPriority() | 普通 | 發揮線程的優先級 |
7 | public boolean isInterrupted() | 普通 | 判斷目前線程是否被中斷,如果是,返回true,否則返回false |
8 | public final boolean isAlive() | 普通 | 判斷線程是否在活動,如果是,返回true,否則返回false |
9 | public final void join() throws InterruptedException | 普通 | 等待線程死亡 |
10 | public final synchronized void join(long millis) throws InterruptedException | 普通 | 等待millis毫秒后,線程死亡 |
11 | public void run() | 普通 | 執行線程 |
12 | public final void setName(String name) | 普通 | 設定線程名稱 |
13 | public final void setPriority(int newPriority) | 普通 | 設定線程的優先值 |
14 | public static void sleep(long millis) throws InterruptedException | 普通 | 使目前正在執行的線程休眠millis毫秒 |
15 | public void start() | 普通 | 開始執行線程 |
16 | public static void yield() | 普通 | 將目前正在執行的線程暫停,允許其它線程執行 |
17 | public final void setDaemon(boolean on) | 普通 | 將一個線程設置成后臺運行 |
18 | public final void setPriority(int newPriority) | 普通 | 更改線程的優先級
|
5.1、守護線程-后臺資源
setDaemon
public final void setDaemon(boolean on)將該線程標記為守護線程或用戶線程。
當正在運行的線程都是守護線程時,Java 虛擬機退出。
該方法必須在啟動線程前調用。
該方法首先調用該線程的 checkaccess 方法,且不帶任何參數。這可能拋出 SecurityException(在當前線程中)。
參數:
on - 如果為 true,則將該線程標記為守護線程。
拋出:
IllegalThreadStateException - 如果該線程處于活動狀態。
SecurityException - 如果當前線程無法修改該線程。
當前臺線程都結束時,后臺線程自動結束。
5.2、線程優先級
setPriority
public final void setPriority(int newPriority)更改線程的優先級。
首先調用線程的 checkAccess 方法,且不帶任何參數。這可能拋出 SecurityException。
在其他情況下,線程優先級被設定為指定的 newPriority 和該線程的線程組的最大允許優先級相比較小的一個。
參數:
newPriority - 要為線程設定的優先級
拋出:
IllegalArgumentException - 如果優先級不在 MIN_PRIORITY 到 MAX_PRIORITY 范圍內。
10-----1------------5
static int | MAX_PRIORITY 線程可以具有的最高優先級。 |
static int | MIN_PRIORITY 線程可以具有的最低優先級。 |
static int | NORM_PRIORITY 分配給線程的默認優先級。 |
SecurityException - 如果當前線程無法修改該線程。
getPriority
public final int getPriority()返回線程的優先級。
返回:
該線程的優先級。
作用:阻塞指定的線程等到另一個線程完成以后,再繼續執行
package com.pb.thread.demo2;public class MyThread implements Runnable { @Override public void run() { for(int x=0;x<10;x++){ System.out.println(Thread.currentThread().getName()+"....."+x); } }}//=============package com.pb.thread.demo2;public class Demo { public static void main(String[] args) { MyThread my=new MyThread(); Thread t1=new Thread(my); t1.setName("半路加入的線程"); for(int x=0;x<10;x++){ if(x==5){ try { t1.start(); t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"....."+x); } }}
結果:
main.....0main.....1main.....2main.....3main.....4半路加入的線程.....0半路加入的線程.....1半路加入的線程.....2半路加入的線程.....3半路加入的線程.....4半路加入的線程.....5半路加入的線程.....6半路加入的線程.....7半路加入的線程.....8半路加入的線程.....9main.....5main.....6main.....7main.....8main.....9
或者
package com.pb.thread.demo2;public class Test { public static void main(String[] args) { for(int x=0;x<10;x++){ if(x==5){ try { Thread t1=new Thread(new MyThread(),"半路加入的線程"); t1.start(); t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"....."+x); } }}
yield
public static void yield()暫停當前正在執行的線程對象,并執行其他線程。
package com.pb.thread.demo2;public class MyThread implements Runnable { @Override public void run() { for(int x=0;x<10;x++){ System.out.println(Thread.currentThread().getName()+"....."+x); Thread.yield(); } }}//===========package com.pb.thread.demo2;public class Test { public static void main(String[] args) { new Thread(new MyThread(),"線程一").start(); new Thread(new MyThread(),"線程二").start(); }}
八、停止線程
開啟多線程,運行代碼通常是循環結構
只要控制住循環,就可以讓run方法結束。也就是線程結束。
package com.pb.thread.demo4;public class StopThread implements Runnable {private boolean flag=true; @Override public void run() { while(flag){ System.out.println(Thread.currentThread().getName()+"......run"); } } public void setChangeFlag(){ this.flag=false; } public static void main(String[] args) { StopThread st=new StopThread(); Thread t1=new Thread(st); Thread t2=new Thread(st); t1.start(); t2.start(); int num=0; while(true){ if(num++==60){ st.setChangeFlag(); break; } System.out.println(Thread.currentThread().getName()+"===="+num); } }}
interrupt
public void interrupt()
如果線程在調用 Object
類的 wait()
、wait(long)
或 wait(long, int)
方法,或者該類的 join()
、join(long)
、join(long, int)
、sleep(long)
或 sleep(long, int)
方法過程中受阻,則其中斷狀態將被清除,它還將收到一個 InterruptedException
。
package com.pb.thread.demo4;public class StopThread implements Runnable { private boolean flag = true; @Override public synchronized void run() { while (flag) { try { wait(); } catch (InterruptedException e) { // e.printStackTrace(); System.out.println(Thread.currentThread().getName() + "......Exception"); flag = false; //設置標識為false } System.out.println(Thread.currentThread().getName() + "......run"); } } public void setChangeFlag() { this.flag = false; } public static void main(String[] args) { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.start(); int num = 0; while (true) { if (num++ == 60) { //中斷狀態也就是凍結狀態,回到運行狀態 t1.interrupt(); t2.interrupt(); break; } System.out.println(Thread.currentThread().getName() + "====" + num); } System.out.println("over"); }}
main====1main====2main====3main====4main====5main====6main====7main====8main====9main====10main====11main====12main====13main====14main====15main====16main====17main====18main====19main====20main====21main====22main====23main====24main====25main====26main====27main====28main====29main====30main====31main====32main====33main====34main====35main====36main====37main====38main====39main====40main====41main====42main====43main====44main====45main====46main====47main====48main====49main====50main====51main====52main====53main====54main====55main====56main====57main====58main====59main====60overThread-1......ExceptionThread-1......runThread-0......ExceptionThread-0......run
九、sleep();
sleep
public static void sleep(long millis) throws InterruptedException
在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和準確性的影響。該線程不丟失任何監視器的所屬權。
參數:
millis
- 以毫秒為單位的休眠時間。
拋出:
InterruptedException
- 如果任何線程中斷了當前線程。當拋出該異常時,當前線程的中斷狀態 被清除。
toString
public String toString()
返回該線程的字符串表示形式,包括線程名稱、優先級和線程組。
Object
中的 toString
package com.pb.thread.demo4;public class StopThread implements Runnable { private boolean flag = true; @Override public synchronized void run() { while (flag) { System.out.println(Thread.currentThread().toString()+ "......run"); } } public void setChangeFlag() { this.flag = false; } public static void main(String[] args) { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.start(); int num = 0; while (true) { if (num++ == 60) { st.setChangeFlag(); break; } System.out.println(Thread.currentThread().toString()+ "====" + num); } System.out.println("over"); }}
Thread[Thread-0,5,main]......runThread[main,5,main]====1Thread[Thread-0,5,main]......runThread[main,5,main]====2Thread[Thread-0,5,main]......runThread[main,5,main]====3Thread[Thread-0,5,main]......runThread[main,5,main]====4Thread[main,5,main]====5Thread[main,5,main]====6Thread[main,5,main]====7Thread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[main,5,main]====8Thread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[main,5,main]====9Thread[Thread-0,5,main]......runThread[main,5,main]====10Thread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[main,5,main]====11Thread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[main,5,main]====12Thread[main,5,main]====13Thread[main,5,main]====14Thread[main,5,main]====15Thread[main,5,main]====16Thread[Thread-0,5,main]......runThread[main,5,main]====17Thread[main,5,main]====18Thread[main,5,main]====19Thread[main,5,main]====20Thread[main,5,main]====21Thread[main,5,main]====22Thread[main,5,main]====23Thread[main,5,main]====24Thread[main,5,main]====25Thread[main,5,main]====26Thread[main,5,main]====27Thread[main,5,main]====28Thread[main,5,main]====29Thread[main,5,main]====30Thread[main,5,main]====31Thread[main,5,main]====32Thread[main,5,main]====33Thread[main,5,main]====34Thread[main,5,main]====35Thread[main,5,main]====36Thread[main,5,main]====37Thread[main,5,main]====38Thread[main,5,main]====39Thread[main,5,main]====40Thread[main,5,main]====41Thread[main,5,main]====42Thread[main,5,main]====43Thread[main,5,main]====44Thread[main,5,main]====45Thread[main,5,main]====46Thread[main,5,main]====47Thread[main,5,main]====48Thread[main,5,main]====49Thread[main,5,main]====50Thread[main,5,main]====51Thread[main,5,main]====52Thread[main,5,main]====53Thread[main,5,main]====54Thread[main,5,main]====55Thread[main,5,main]====56Thread[main,5,main]====57Thread[main,5,main]====58Thread[main,5,main]====59Thread[main,5,main]====60overThread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......runThread[main,5,main]====1Thread[Thread-0,5,main]......runThread[main,5,main]====2Thread[Thread-0,5,main]......runThread[main,5,main]====3Thread[Thread-0,5,main]......runThread[main,5,main]====4Thread[main,5,main]====5Thread[main,5,main]====6Thread[main,5,main]====7Thread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[main,5,main]====8Thread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[main,5,main]====9Thread[Thread-0,5,main]......runThread[main,5,main]====10Thread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[main,5,main]====11Thread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[Thread-0,5,main]......runThread[main,5,main]====12Thread[main,5,main]====13Thread[main,5,main]====14Thread[main,5,main]====15Thread[main,5,main]====16Thread[Thread-0,5,main]......runThread[main,5,main]====17Thread[main,5,main]====18Thread[main,5,main]====19Thread[main,5,main]====20Thread[main,5,main]====21Thread[main,5,main]====22Thread[main,5,main]====23Thread[main,5,main]====24Thread[main,5,main]====25Thread[main,5,main]====26Thread[main,5,main]====27Thread[main,5,main]====28Thread[main,5,main]====29Thread[main,5,main]====30Thread[main,5,main]====31Thread[main,5,main]====32Thread[main,5,main]====33Thread[main,5,main]====34Thread[main,5,main]====35Thread[main,5,main]====36Thread[main,5,main]====37Thread[main,5,main]====38Thread[main,5,main]====39Thread[main,5,main]====40Thread[main,5,main]====41Thread[main,5,main]====42Thread[main,5,main]====43Thread[main,5,main]====44Thread[main,5,main]====45Thread[main,5,main]====46Thread[main,5,main]====47Thread[main,5,main]====48Thread[main,5,main]====49Thread[main,5,main]====50Thread[main,5,main]====51Thread[main,5,main]====52Thread[main,5,main]====53Thread[main,5,main]====54Thread[main,5,main]====55Thread[main,5,main]====56Thread[main,5,main]====57Thread[main,5,main]====58Thread[main,5,main]====59Thread[main,5,main]====60overThread[Thread-0,5,main]......run
package com.pb.thread.demo4;/* * 匿名內部類實現多線程 */public class ThreadTest { public static void main(String[] args) { //線程對象 new Thread(){ public void run(){ for (int x = 0; x < 100; x++) { System.out.println(Thread.currentThread().getName()+".........."+x); } } }.start(); //Runnable 接口 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(); }}
新聞熱點
疑難解答