java中的多线程 在java中要想实现多线程�有两种手段�一种是继续Thread类�另外一种是实现Runable接口。
对于直接继承Thread的类来说�代码大致框架是� ?
1
2
3
4
5
6
7
8
9
10
11
12
class 类名extends Thread{
方法1;
方法2�
…
public void run(){
// other code…
}
属性1�
属性2�
…
}
先看一个简单的例子� ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
/**
* @author Rollen-Holt 继承Thread类,直接调用run方法
* */
class helloextends Thread {
public hello() {
}
public hello(String name) {
this.name = name;
}
public void run() {
for (int i =0; i <5; i++) {
System.out.println(name +"运行 " + i);
}
}
public static void main(String[] args) { 5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
hello h1=new hello("A");
hello h2=new hello("B");
h1.run();
h2.run();
}
private String name;
}
【运行结果】� A运行 0 A运行 1 A运行 2 A运行 3 A运行 4 B运行 0 B运行 1 B运行 2 B运行 3 B运行 4 我们会发现这些都是顺序执行的�说明我们的调用方法不对�应该调用的是start��方法。
当我们把上面的主函数修改为如下所示的时候� ?
1
2
3
4
5
6
public static void main(String[] args) {
hello h1=new hello("A");
hello h2=new hello("B");
h1.start();
h2.start();
}
然后运行程序�输出的可能的结果如下� A运行 0 B运行 0 B运行 1 B运行 2 B运行 3 B运行 4 A运行 1 A运行 2 A运行 3 A运行 4
因为需要用到CPU的资源�所以每次的运行结果基本是都不一样的�呵呵。
注意�虽然我们在这里调用的是start��方法�但是实际上调用的还是run��方法的主体。
那么�为什么我们不能直接调用run��方法呢�
我的理解是�线程的运行需要本地操作系统的支持。
如果你查看start的源代码的时候�会发现� ?
1
2
3
4
5
6
7
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW". 8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
*/
if (threadStatus !=0 ||this != me)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
private native void start0();
注意我用红色加粗的那一条语句�说明此处调用的是start0��。并且这个这个方法用了native
关键字�次关键字表示调用本地操作系统的函数。因为多线程的实现需要本地操作系统的支持。
但是start方法重复调用的话�会出现java.lang.IllegalThreadStateException异常。 通过实现Runnable接口�
大致框架是� ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
class 类名implements Runnable{
方法1;
方法2�
…
public void run(){
// other code…
}
属性1�
属性2�
…
}
来先看一个小例子吧� ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
/**
* @author Rollen-Holt 实现Runnable接口
* */
class helloimplements Runnable {
public hello() {
}
public hello(String name) {
this.name = name;
}
public void run() {
for (int i =0; i <5; i++) {
System.out.println(name +"运行 " + i);
}
}
public static void main(String[] args) {
hello h1=new hello("线程A");
Thread demo=new Thread(h1);
hello h2=new hello("线程�");
Thread demo1=new Thread(h2);
demo.start();
demo1.start();
}
private String name;
}
5
2
6
2
7
2
8
2
9
3
0 【可能的运行结果】� 线程A运行 0 线程�运行 0 线程�运行 1 线程�运行 2 线程�运行 3 线程�运行 4 线程A运行 1 线程A运行 2 线程A运行 3 线程A运行 4
关于选择继承Thread还是实现Runnable接口�
其实Thread也是实现Runnable接口的� ?
1
2
3
4
5
6
7
8
class Threadimplements Runnable {
//…
public void run() {
if (target !=null) {
target.run();
}
}
}
其实Thread中的run方法调用的是Runnable接口的run方法。不知道大家发现没有�Thread和Runnable都实现了run方法�这种操作模式其实就是代理模式。关于代理模式�我曾经写过一个小例子呵呵�大家
有 兴 趣 的 话 可 以 看 一 下 �http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144847.html
Thread和Runnable的区别�
如果一个类继承Thread�则不适合资源共享。但是如果实现了Runable接口的话�则很容易的
实现资源共享。 ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
/**
* @author Rollen-Holt 继承Thread类�不能资源共享
* */
class helloextends Thread {
public void run() {
for (int i =0; i <7; i++) {
if (count >0) {
System.out.println("count= " + count--);
}
}
}
public static void main(String[] args) {
hello h1 =new hello();
hello h2 =new hello();
hello h3 =new hello();
h1.start();
h2.start();
h3.start();
}
private int count =5;
}
2
3
【运行结果】� count= 5 count= 4 count= 3 count= 2 count= 1 count= 5 count= 4 count= 3 count= 2 count= 1 count= 5 count= 4 count= 3 count= 2 count= 1
大家可以想象�如果这个是一个买票系统的话�如果count表示的是车票的数量的话�说明并没有
实现资源的共享。
我们换为Runnable接口
?
1
2
3
4
5
6
7
8
9
class MyThreadimplements Runnable{
private int ticket =5; //5张票
public void run() {
for (int i=0; i<=20; i++) {
if (this.ticket >0) {
System.out.println(Thread.currentThread().getName()+"正在
卖票"+this.ticket--); 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
}
}
}
}
public class lzwCode {
public static void main(String [] args) {
MyThread my =new MyThread();
new Thread(my,"1号窗口").start();
new Thread(my,"2号窗口").start();
new Thread(my,"3号窗口").start();
}
}
【运行结果】� count= 5 count= 4 count= 3 count= 2 count= 1
总结一下吧�
实现Runnable接口比继承Thread类所具有的优势� 1��适合多个相同的程序代码的线程去处理同一个资源
2��可以避免java中的单继承的限制
3��增加程序的健壮性�代码可以被多个线程共享�代码和数据独立。
所以�本人建议大家劲量实现接口。
?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
/**
* @author Rollen-Holt
* 取得线程的名称
* */
class helloimplements Runnable {
public void run() {
for (int i =0; i <3; i++) {
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args) {
hello he =new hello();
new Thread(he,"A").start();
new Thread(he,"B").start();
new Thread(he).start();
}
}
【运行结果】� A A A B B B Thread-0 Thread-0 Thread-0 说明如果我们没有指定名字的话�系统自动提供名字。 提醒一下大家�main方法其实也是一个线程。在java中所以的线程都是同时启动的�至于什么时候�哪
个先执行�完全看谁先得到CPU的资源。
在java中�每次程序运行至少启动2个线程。一个是main线程�一个是垃圾收集线程。因为每当
使用java命令执行一个类的时候�实际上都会启动一个����每一个���实习在就是在操作系
统中启动了一个进程。 判断线程是否启动 ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
/**
* @author Rollen-Holt 判断线程是否启动
* */
class helloimplements Runnable {
public void run() {
for (int i =0; i <3; i++) {
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args) {
hello he =new hello();
Thread demo =new Thread(he);
System.out.println("线程启动之前---》" + demo.isAlive());
demo.start();
System.out.println("线程启动之后---》" + demo.isAlive());
}
}
1
8 【运行结果】 线程启动之前---》false 线程启动之后---》true Thread-0 Thread-0 Thread-0 主线程也有可能在子线程结束之前结束。并且子线程不受影响�不会因为主线程的结束而结束。
线程的强制执行� ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
/**
* @author Rollen-Holt 线程的强制执行
* */
class helloimplements Runnable {
public void run() {
for (int i =0; i <3; i++) {
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args) {
hello he =new hello();
Thread demo =new Thread(he,"线程");
demo.start();
for(int i=0;i<50;++i){
if(i>10){
try{
demo.join(); //强制执行demo
}catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("main 线程执行-->"+i);
}
}
}
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6 【运行的结果】� main 线程执行-->0 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 ���
线程的休眠� ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
/**
* @author Rollen-Holt 线程的休眠
* */
class helloimplements Runnable {
public void run() {
for (int i =0; i <3; i++) {
try {
Thread.sleep(2000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i);
}
}
public static void main(String[] args) {
hello he =new hello();
Thread demo =new Thread(he,"线程");
demo.start();
}
}
【运行结果】��结果每隔2s输出一个� 线程0 线程1 线程2 线程的中断� ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
/**
* @author Rollen-Holt 线程的中断
* */
class helloimplements Runnable {
public void run() {
System.out.println("执行run方法");
try {
Thread.sleep(10000);
System.out.println("线程完成休眠");
}catch (Exception e) {
System.out.println("休眠被打断");
return; //返回到程序的调用处
}
System.out.println("线程正常终止");
}
public static void main(String[] args) {
hello he =new hello();
Thread demo =new Thread(he,"线程");
demo.start();
try{
Thread.sleep(2000);
}catch (Exception e) {
e.printStackTrace();
}
demo.interrupt();//2s后中断线程
}
}
2
6
2
7
2
8 【运行结果】� 执行run方法 休眠被打断
在java程序中�只要前台有一个线程在运行�整个java程序进程不会小时�所以此时可以设置一
个后台线程�这样即使java进程小时了�此后台线程依然能够继续运行。 ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
/**
* @author Rollen-Holt 后台线程
* */
class helloimplements Runnable {
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() +"在运行
");
}
}
public static void main(String[] args) {
hello he =new hello();
Thread demo =new Thread(he,"线程");
demo.setDaemon(true);
demo.start();
}
}
虽然有一个死循环�但是程序还是可以执行完的。因为在死循环中的线程操作已经设置为后台运行了。 线程的优先级� ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
/**
* @author Rollen-Holt 线程的优先级
* */
class helloimplements Runnable {
public void run() {
for(int i=0;i<5;++i){
System.out.println(Thread.currentThread().getName()+"运 行
"+i);
}
}
public static void main(String[] args) {
Thread h1=new Thread(new hello(),"A");
Thread h2=new Thread(new hello(),"B");
Thread h3=new Thread(new hello(),"C");
h1.setPriority(8);
h2.setPriority(2);
h3.setPriority(6);
h1.start();
h2.start();
h3.start();
}
}
【运行结果】� A运行0 A运行1 A运行2 A运行3 A运行4 B运行0 C运行0 C运行1 C运行2 C运行3 C运行4 B运行1 B运行2 B运行3 B运行4 。但是请读者不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源、 另外�主线程的优先级是5. 线程的礼让。 在线程操作中�也可以使用yield��方法�将一个线程的操作暂时交给其他线程执行。 ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
/**
* @author Rollen-Holt 线程的优先级
* */
class helloimplements Runnable {
public void run() {
for(int i=0;i<5;++i){
System.out.println(Thread.currentThread().getName()+"运 行
"+i);
if(i==3){
System.out.println("线程的礼让");
Thread.currentThread().yield();
}
}
}
public static void main(String[] args) { 3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
Thread h1=new Thread(new hello(),"A");
Thread h2=new Thread(new hello(),"B");
h1.start();
h2.start();
}
}
A运行0 A运行1 A运行2 A运行3 线程的礼让 A运行4 B运行0 B运行1 B运行2 B运行3 线程的礼让 B运行4
同步和死锁�
【问题引出】:比如说对于买票系统�有下面的代码� ? 1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
/**
* @author Rollen-Holt
* */
class helloimplements Runnable {
public void run() {
for(int i=0;i<10;++i){
if(count>0){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(count--);
}
}
}
public static void main(String[] args) {
hello he=new hello();
Thread h1=new Thread(he);
Thread h2=new Thread(he);
Thread h3=new Thread(he);
h1.start();
h2.start();
h3.start();
}
private int count=5;
}
7
2
8 【运行结果】� 5 4 3 2 1 0 -1
这里出现了-1�显然这个是错的。�应该票数不能为负值。
如果想解决这种问题�就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行�
其他的线程必须等到这个线程结束之后才能继续执行。
【使用线程同步解决问题】
采用同步的话�可以使用同步代码块和同步方法两种来完成。
【同步代码块】�
语法格式�
synchronized�同步对象�{
//需要同步的代码
}
但是一般都把当前对象this作为同步对象。
比如对于上面的买票的问题�如下� ?
1
2
3
4
5
6
7
8
/**
* @author Rollen-Holt
* */
class helloimplements Runnable {
public void run() {
for(int i=0;i<10;++i){
synchronized (this) {
if(count>0){ 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(count--);
}
}
}
}
public static void main(String[] args) {
hello he=new hello();
Thread h1=new Thread(he);
Thread h2=new Thread(he);
Thread h3=new Thread(he);
h1.start();
h2.start();
h3.start();
}
private int count=5;
}
【运行结果】��每一秒输出一个结果� 5 4 3 2 1
【同步方法】
也可以采用同步方法。
语法格式为synchronized 方法返回类型方法名�参数列表�{ // 其他代码 } 现在�我们采用同步方法解决上面的问题。 ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
/**
* @author Rollen-Holt
* */
class helloimplements Runnable {
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(count--);
}
}
public static void main(String[] args) {
hello he =new hello();
Thread h1 =new Thread(he);
Thread h2 =new Thread(he); 1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
3
2
3
3
Thread h3 =new Thread(he);
h1.start();
h2.start();
h3.start();
}
private int count =5;
}
【运行结果】�每秒输出一个� 5 4 3 2 1
提醒一下�当多个线程共享一个资源的时候需要进行同步�但是过多的同步可能导致死锁。
此处列举经典的生产者和消费者问题。 【生产者和消费者问题】
先看一段有问题的代码。 ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
class Info {
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;
}
private String name ="Rollen";
private int age =20;
}
/**
* 生产者
* */
class Producerimplements Runnable{
private Info info=null;
Producer(Info info){
this.info=info;
}
public void run(){
boolean flag=false;
for(int i=0;i<25;++i){
if(flag){
this.info.setName("Rollen");
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace(); 5
2
6
2
7
2
8
2
9
3
0
3
1
3
2
3
3
3
4
3
5
3
6
3
7
3
8
3
9
4
0
4
1
4
2
4
3
4
4
4
5
4
6
4
}
this.info.setAge(20);
flag=false;
}else{
this.info.setName("chunGe");
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
this.info.setAge(100);
flag=true;
}
}
}
}
/**
* 消费者类
* */
class Consumerimplements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
public void run(){
for(int i=0;i<25;++i){
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(this.info.getName()+"<---->"+this.info.getAge());
}
}
}
/**
* 测试类
* */
class hello{
public static void main(String[] args) {
Info info=new Info(); 7
4
8
4
9
5
0
5
1
5
2
5
3
5
4
5
5
5
6
5
7
5
8
5
9
6
0
6
1
6
2
6
3
6
4
6
5
6
6
6
7
6
8
6
Producer pro=new Producer(info);
Consumer con=new Consumer(info);
new Thread(pro).start();
new Thread(con).start();
}
}
9
7
0
7
1
7
2
7
3
7
4
7
5
7
6
7
7
7
8
7
9
8
0
8
1
8
2
8
3
8
4
8
5
8
6
8
7
8
8
8
9 【运行结果】� Rollen<---->100 chunGe<---->20 chunGe<---->100 Rollen<---->100 chunGe<---->20 Rollen<---->100 Rollen<---->100 Rollen<---->100 chunGe<---->20 chunGe<---->20 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20
大家可以从结果中看到�名字和年龄并没有对于。
那么如何解决呢� 1�加入同步
2�加入等待和唤醒 先来看看加入同步会是如何。 ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
class Info {
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 synchronized void set(String name,int age){
this.name=name;
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
this.age=age;
}
public synchronized void get(){
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(this.getName()+"<===>"+this.getAge());
}
private String name ="Rollen";
private int age =20;
}
/**
* 生产者
* */ 2
7
2
8
2
9
3
0
3
1
3
2
3
3
3
4
3
5
3
6
3
7
3
8
3
9
4
0
4
1
4
2
4
3
4
4
4
5
4
6
4
7
4
8
class Producerimplements Runnable {
private Info info =null;
Producer(Info info) {
this.info = info;
}
public void run() {
boolean flag =false;
for (int i =0; i <25; ++i) {
if (flag) {
this.info.set("Rollen",20);
flag =false;
}else {
this.info.set("ChunGe",100);
flag =true;
}
}
}
}
/**
* 消费者类
* */
class Consumerimplements Runnable {
private Info info =null;
public Consumer(Info info) {
this.info = info;
}
public void run() {
for (int i =0; i <25; ++i) {
try {
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
this.info.get();
}
}
}
4
9
5
0
5
1
5
2
5
3
5
4
5
5
5
6
5
7
5
8
5
9
6
0
6
1
6
2
6
3
6
4
6
5
6
6
6
7
6
8
6
9
7
0
/**
* 测试类
* */
class hello {
public static void main(String[] args) {
Info info =new Info();
Producer pro =new Producer(info);
Consumer con =new Consumer(info);
new Thread(pro).start();
new Thread(con).start();
}
}
7
1
7
2
7
3
7
4
7
5
7
6
7
7
7
8
7
9
8
0
8
1
8
2
8
3
8
4
8
5
8
6
8
7
8
8
8
9
9
0
9
1
9
2 9
3
9
4
9
5
9
6
9
7
9
8
9
9 【运行结果】� Rollen<===>20 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 Rollen<===>20 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100
从运行结果来看�错乱的问题解决了�现在是Rollen 对应20�ChunGe对于100
�但是还是出现了重复读取的问题�也肯定有重复覆盖的问题。如果想解决这个问题�就需要使用
Object类帮忙了、
�我们可以使用其中的等待和唤醒操作。
要完成上面的功能�我们只需要修改Info类饥渴�在其中加上标志位�并且通过判断标志位完成等
待和唤醒的操作�代码如下� ?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
class Info {
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 synchronized void set(String name,int age){
if(!flag){
try{
super.wait();
}catch (Exception e) {
e.printStackTrace();
}
} 8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
3
2
3
3
3
4
3
5
3
6
3
7
3
8
3
9
4
this.name=name;
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
this.age=age;
flag=false;
super.notify();
}
public synchronized void get(){
if(flag){
try{
super.wait();
}catch (Exception e) {
e.printStackTrace();
}
}
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(this.getName()+"<===>"+this.getAge());
flag=true;
super.notify();
}
private String name ="Rollen";
private int age =20;
private boolean flag=false;
}
/**
* 生产者
* */
class Producerimplements Runnable {
private Info info =null;
Producer(Info info) {
this.info = info;
}
0
4
1
4
2
4
3
4
4
4
5
4
6
4
7
4
8
4
9
5
0
5
1
5
2
5
3
5
4
5
5
5
6
5
7
5
8
5
9
6
0
6
1
6
public void run() {
boolean flag =false;
for (int i =0; i <25; ++i) {
if (flag) {
this.info.set("Rollen",20);
flag =false;
}else {
this.info.set("ChunGe",100);
flag =true;
}
}
}
}
/**
* 消费者类
* */
class Consumerimplements Runnable {
private Info info =null;
public Consumer(Info info) {
this.info = info;
}
public void run() {
for (int i =0; i <25; ++i) {
try {
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
this.info.get();
}
}
}
/**
* 测试类
* */
class hello {
public static void main(String[] args) {
Info info =new Info();
Producer pro =new Producer(info); 2
6
3
6
4
6
5
6
6
6
7
6
8
6
9
7
0
7
1
7
2
7
3
7
4
7
5
7
6
7
7
7
8
7
9
8
0
8
1
8
2
8
3
8
Consumer con =new Consumer(info);
new Thread(pro).start();
new Thread(con).start();
}
}
4
8
5
8
6
8
7
8
8
8
9
9
0
9
1
9
2
9
3
9
4
9
5
9
6
9
7
9
8
9
9
1
0
0
1
0
1
1
0
2
1
0
3
10
4
1
0
5
1
0
6
1
0
7
1
0
8
1
0
9
1
1
0
1
1
1
1
1
2
1
1
3
1
1
4
1
1
5
1
1
6
1
1
7
1
1
8 1
1
9
?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
【程序运行结果】�
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
先在看结果就可以知道�之前的问题完全解决。
2
5
2
6
2
7