一、线程之间的通信
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,1
Thread-1,2
Thread-0,3
Thread-1,4
Thread-0,5
Thread-1,6
Thread-0,7
Thread-1,8
Thread-0,9
Thread-1,10
Thread-0,11
Thread-1,12
Thread-0,13
Thread-1,14
Thread-0,15
Thread-1,16
Thread-0,17
Thread-1,18
Thread-0,19
Thread-1,20
Thread-0,21
Thread-1,22
Thread-0,23
Thread-1,24
Thread-0,25
Thread-1,26
Thread-0,27
Thread-1,28
Thread-0,29
Thread-1,30
Thread-0,31
Thread-1,32
Thread-0,33
Thread-1,34
Thread-0,35
Thread-1,36
Thread-0,37
Thread-1,38
Thread-0,39
Thread-1,40
Thread-0,41
Thread-1,42
Thread-0,43
Thread-1,44
Thread-0,45
Thread-1,46
Thread-0,47
Thread-1,48
Thread-0,49
Thread-1,50
Thread-0,51
Thread-1,52
Thread-0,53
Thread-1,54
Thread-0,55
Thread-1,56
Thread-0,57
Thread-1,58
Thread-0,59
Thread-1,60
Thread-0,61
Thread-1,62
Thread-0,63
Thread-1,64
Thread-0,65
Thread-1,66
Thread-0,67
Thread-1,68
Thread-0,69
Thread-1,70
Thread-0,71
Thread-1,72
Thread-0,73
Thread-1,74
Thread-0,75
Thread-1,76
Thread-0,77
Thread-1,78
Thread-0,79
Thread-1,80
Thread-0,81
Thread-1,82
Thread-0,83
Thread-1,84
Thread-0,85
Thread-1,86
Thread-0,87
Thread-1,88
Thread-0,89
Thread-1,90
Thread-0,91
Thread-1,92
Thread-0,93
Thread-1,94
Thread-0,95
Thread-1,96
Thread-0,97
Thread-1,98
Thread-0,99
Thread-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---生产者---产品...20901
Thread-1--------消费者------------产品...20901
Thread-0---生产者---产品...20902
Thread-1--------消费者------------产品...20902
Thread-0---生产者---产品...20903
Thread-1--------消费者------------产品...20903
Thread-0---生产者---产品...20904
Thread-1--------消费者------------产品...20904
Thread-0---生产者---产品...20905
Thread-1--------消费者------------产品...20905
Thread-0---生产者---产品...20906
Thread-1--------消费者------------产品...20906
Thread-0---生产者---产品...20907
Thread-1--------消费者------------产品...20907
Thread-0---生产者---产品...20908
Thread-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.....0
main.....1
main.....2
main.....3
main.....4
半路加入的线程.....0
半路加入的线程.....1
半路加入的线程.....2
半路加入的线程.....3
半路加入的线程.....4
半路加入的线程.....5
半路加入的线程.....6
半路加入的线程.....7
半路加入的线程.....8
半路加入的线程.....9
main.....5
main.....6
main.....7
main.....8
main.....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====1
main====2
main====3
main====4
main====5
main====6
main====7
main====8
main====9
main====10
main====11
main====12
main====13
main====14
main====15
main====16
main====17
main====18
main====19
main====20
main====21
main====22
main====23
main====24
main====25
main====26
main====27
main====28
main====29
main====30
main====31
main====32
main====33
main====34
main====35
main====36
main====37
main====38
main====39
main====40
main====41
main====42
main====43
main====44
main====45
main====46
main====47
main====48
main====49
main====50
main====51
main====52
main====53
main====54
main====55
main====56
main====57
main====58
main====59
main====60
over
Thread-1......Exception
Thread-1......run
Thread-0......Exception
Thread-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]......run
Thread[main,5,main]====1
Thread[Thread-0,5,main]......run
Thread[main,5,main]====2
Thread[Thread-0,5,main]......run
Thread[main,5,main]====3
Thread[Thread-0,5,main]......run
Thread[main,5,main]====4
Thread[main,5,main]====5
Thread[main,5,main]====6
Thread[main,5,main]====7
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====8
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====9
Thread[Thread-0,5,main]......run
Thread[main,5,main]====10
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====11
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====12
Thread[main,5,main]====13
Thread[main,5,main]====14
Thread[main,5,main]====15
Thread[main,5,main]====16
Thread[Thread-0,5,main]......run
Thread[main,5,main]====17
Thread[main,5,main]====18
Thread[main,5,main]====19
Thread[main,5,main]====20
Thread[main,5,main]====21
Thread[main,5,main]====22
Thread[main,5,main]====23
Thread[main,5,main]====24
Thread[main,5,main]====25
Thread[main,5,main]====26
Thread[main,5,main]====27
Thread[main,5,main]====28
Thread[main,5,main]====29
Thread[main,5,main]====30
Thread[main,5,main]====31
Thread[main,5,main]====32
Thread[main,5,main]====33
Thread[main,5,main]====34
Thread[main,5,main]====35
Thread[main,5,main]====36
Thread[main,5,main]====37
Thread[main,5,main]====38
Thread[main,5,main]====39
Thread[main,5,main]====40
Thread[main,5,main]====41
Thread[main,5,main]====42
Thread[main,5,main]====43
Thread[main,5,main]====44
Thread[main,5,main]====45
Thread[main,5,main]====46
Thread[main,5,main]====47
Thread[main,5,main]====48
Thread[main,5,main]====49
Thread[main,5,main]====50
Thread[main,5,main]====51
Thread[main,5,main]====52
Thread[main,5,main]====53
Thread[main,5,main]====54
Thread[main,5,main]====55
Thread[main,5,main]====56
Thread[main,5,main]====57
Thread[main,5,main]====58
Thread[main,5,main]====59
Thread[main,5,main]====60
over
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====1
Thread[Thread-0,5,main]......run
Thread[main,5,main]====2
Thread[Thread-0,5,main]......run
Thread[main,5,main]====3
Thread[Thread-0,5,main]......run
Thread[main,5,main]====4
Thread[main,5,main]====5
Thread[main,5,main]====6
Thread[main,5,main]====7
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====8
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====9
Thread[Thread-0,5,main]......run
Thread[main,5,main]====10
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====11
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run
Thread[main,5,main]====12
Thread[main,5,main]====13
Thread[main,5,main]====14
Thread[main,5,main]====15
Thread[main,5,main]====16
Thread[Thread-0,5,main]......run
Thread[main,5,main]====17
Thread[main,5,main]====18
Thread[main,5,main]====19
Thread[main,5,main]====20
Thread[main,5,main]====21
Thread[main,5,main]====22
Thread[main,5,main]====23
Thread[main,5,main]====24
Thread[main,5,main]====25
Thread[main,5,main]====26
Thread[main,5,main]====27
Thread[main,5,main]====28
Thread[main,5,main]====29
Thread[main,5,main]====30
Thread[main,5,main]====31
Thread[main,5,main]====32
Thread[main,5,main]====33
Thread[main,5,main]====34
Thread[main,5,main]====35
Thread[main,5,main]====36
Thread[main,5,main]====37
Thread[main,5,main]====38
Thread[main,5,main]====39
Thread[main,5,main]====40
Thread[main,5,main]====41
Thread[main,5,main]====42
Thread[main,5,main]====43
Thread[main,5,main]====44
Thread[main,5,main]====45
Thread[main,5,main]====46
Thread[main,5,main]====47
Thread[main,5,main]====48
Thread[main,5,main]====49
Thread[main,5,main]====50
Thread[main,5,main]====51
Thread[main,5,main]====52
Thread[main,5,main]====53
Thread[main,5,main]====54
Thread[main,5,main]====55
Thread[main,5,main]====56
Thread[main,5,main]====57
Thread[main,5,main]====58
Thread[main,5,main]====59
Thread[main,5,main]====60
over
Thread[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();
} }