一、线程之间的通信
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(); }}
三、JDK 1.5新特性
一、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()返回线程的优先级。
返回:
该线程的优先级。
六、join线程
作用:阻塞指定的线程等到另一个线程完成以后,再继续执行
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
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
toString
public String 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(); }}