您的位置:首页 > 编程语言 > Java开发

java多线程之间通信

2017-07-22 14:12 176 查看
Java中线程间通信

1.      线程间通信(通讯): 多个线程在处理同一个资源,但任务不同。

一、等待/唤醒机制:

1.  涉及的方法:

(1) wait(); 使线程处于冻结状态,被wait的线程会存储到线程池(等待集)中;

(2) notify(); 唤醒线程池中的一个线程,这个线程是任意的;

(3) notifyAll(); 唤醒线程池中的所有线程。

2.  这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法;而且必须要明确到底操作的是哪个锁上的线程。即必须明确线程由那个监视器监视。

3.  监视器: 就是所说的锁。

4. 为什么操作线程的方法wait()、notify()、notifyAll()定义在了Object类中?

答:因为这些方法就是监视器的方法,监视器就是锁,锁可以是任意的对象,如Object obj = new Object();既然可以是任意对象,那么这些方法需要定义在最高的类中,即定义在Object类中。

5.     线程间通信的示例:

//创建一个资源类,存放资源
class Resource {

    private String
name;
    private String
sex;
    private
boolean
flag = false;
    public
synchronized void
input(String
name, String sex) {
    if (flag)
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
    this.name =
name;
    this.sex =
sex;
    flag = true;
    this.notify();
    }
 
    public
synchronized void
output() {
    if (!flag)
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
    System.out.println(name +
" 的性别:   " +
sex);
    flag = false;
    this.notify();
    }
}
//创建输入的run方法,利用类对任务进行封装
class Input
implements
Runnable {
    Resource r = null;
 
    Input(Resource r) {
    this.r =
r;
    }
 
    public
void
run() {
    int
x = 0;
    for (int
i = 10; i > 0;
i--) {
        if (x == 0)
        r.input("KangKang",
"男");
        else
        r.input("Jane",
"女");
        x = (x + 1) % 2;
    }
    }
 
}
//利用类实现对输出任务的封装
class Output
implements
Runnable {
    Resource r = null;
    Output(Resource r) {
    this.r =
r;
    }
    public
void
run() {
    for (int
i = 10; i > 0;
i--)
        r.output();
    }
}
//主方法所在的类
public
class
ThreadCommunication {
 
    public
static void
main(String[]
args) {
    Resource r = new Resource();//创建一个资源对象,使下面两个线程同时操作同一个资源对象
    Input in = new Input(r);
    Output out = new Output(r);
    Thread tin = new Thread(in);
    Thread tout = new Thread(out);
    tin.start();
    tout.start();
    }
}

结果:(实现一次赋值,一次输出,两个线程交替进行)
KangKang的性别:   男
Jane 的性别:   女
KangKang的性别:   男
Jane 的性别:   女
KangKang的性别:   男
Jane 的性别:   女
KangKang的性别:   男
Jane 的性别:   女
KangKang的性别:   男
Jane 的性别:   女
6.     生产者—消费者模式:

(1)单生产者—单消费者模式:

class Resource1 {
    private
int
count = 0;//
生产物品编号
    private String
name;
    private
boolean
flag = false;
 
    public
synchronized void
produce(Stringname) {
     
    this.name =
name;
    if (flag)
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
    this.count++;
    System.out.println("生产的 " +
this.name +
"  的编号是: " +
count);
    flag = true;
    this.notify();
    }
 
    public
synchronized void
eat() {
    if (!flag)

        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
     System.out.println("消费者吃掉的   " +
this.name +
"  的编号是: "
           + this.count);
     flag = false;
        this.notify();
    }
}
 
class Producer
implements Runnable {
    private Resource1
r = null;
 
    Producer(Resource1 r) {
    this.r =
r;
    }
 
    public
void
run() {
    for (int
i = 100; i > 0;
i--) {
        r.produce("烤鸭");
    }
    }
 
}
 
class Consumer
implements Runnable {
    private Resource1
r = null;
 
    Consumer(Resource1 r) {
    this.r =
r;
    }
 
    public
void
run() {
    for (int
i = 100; i > 0;
i--)
        r.eat();
    }
}
 
public
class
ProducerConsumerDemo {
    public
static void
main(String[]
args) {
    Resource1 r = new Resource1();
    Producer p
19954
= new Producer(r);
    Consumer c = new Consumer(r);
    Thread tp = new Thread(p);
    Thread tc = new Thread(c);
    tp.start();
    tc.start();
    }
}
 

(2)多生产者—多消费者模式:

①    将if换成while,解决了线程获取执行权后,再次判断flag,决定是否执行;if只能判断一次,判断后如果满足if句则线程wait,等到唤醒后直接执行下面的代码,不再判断;利用while可以解决这个问题,因为while是如果一直 为真,则一直循环,知道不满足才会执行下面的代码。While + notify会导致程序死锁。

②    notifyAll解决了保证能够唤醒对方的线程,而notify只可以唤醒一个线程,可能仍然把本方的线程唤醒,然后本方判断flag不能跳出,导致所有的线程都冻结,产生死锁。

class Resource1 {
    private
int
count = 0;//
生产物品编号
    private String
name;
    private
boolean
flag = false;
    public
synchronized void
produce(Stringname) {
    this.name =
name;
    while (flag) //修改:将if换成while
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
    this.count++;
    System.out.println(Thread.currentThread().getName()+"生产的 " +
this.name +
"  的编号是: " +
count);
    flag = true;
    this.notifyAll();//将notify
换成 notifyAll
    }
 
    public
synchronized void
eat() {
    while(!flag)
//修改:将if换成while
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
     System.out.println(Thread.currentThread().getName()+"消费者吃掉的   "
+ this.name +
"  的编号是: "
           + this.count);
     flag = false;
        this.notifyAll();//将notify
换成 notifyAll
    }
}
 
class Producer
implements Runnable {
    private Resource1
r = null;
 
    Producer(Resource1 r) {
    this.r =
r;
    }
 
    public
void
run() {
    for (int
i = 100; i > 0;
i--) {
        r.produce("烤鸭");
    }
    }
}
 
class Consumer
implements Runnable {
    private Resource1
r = null;
 
    Consumer(Resource1 r) {
    this.r =
r;
    }
 
    public
void
run() {
    for (int
i = 100; i > 0;
i--)
        r.eat();
    }
}
 
public
class
MultiProducerConsumerDemo {
    public
static void
main(String[]
args) {
    Resource1 r = new Resource1();
    Producer p = new Producer(r);
    Producer p1 = new Producer(r);
    Consumer c = new Consumer(r);
    Consumer c1 = new Consumer(r);
    Thread t0 = new Thread(p);
    Thread t1 = new Thread(p1);
    Thread t2 = new Thread(c);
    Thread t3 = new Thread(c1);
    t0.start();
    t1.start();
    t2.start();
    t3.start();
    }
}

7.     Lock接口:的出现替代了同步代码块或者同步方法;将同步的隐式锁操作变成了显式的锁操作,变得更加灵活,并且可以在一个锁上设置多个监视器。Xxx.lock();方法获取锁,unlock();释放锁,通常将xxx.unlock();放在finally语句中。


8.     Condition接口:的出现替代了Object类中的wait、notify、notifyAll方法,将这些监视器方法单独进行了封装,变成Condition监视器对象,可以和任意锁进行组合使用,方法变成await、signal、signalAll。

 

9.     同步代码块:对于锁的操作是隐式的。自从JDK1.5,Lock便取代了synchronized。

·        标准形式:

·        
Lock l = ...;

·        
 l.lock();

·        
 try {

·        
   // access the resource protected by this lock

·        
 } finally {

·        
   l.unlock();

 }


10.  Sleep() 方法和wait() 方法 有什么区别?

答:

(1)Wait可以指定时间,也可以不指定时间,sleep必须指定时间;

(2)在同步中时,对于CPU的执行权和锁的处理不同:wait释放CPU执行权,释放锁,sleep释放CPU执行权,不释放锁(sleep不需要别人叫,wait需要别人叫,所以要释放锁)。

11.  在一个同步中,只能有一个线程执行,但是 可以在一个线程中被唤醒着多个线程,只有获得此同步锁的线程才会执行,被唤醒的其他线程且不具有锁的线程不会执行。

12.  线程停止的方法:①run方法结束;②stop方法。

13.  怎么控制线程的任务结束呢?

答:任务中设置有循环结构,只要控制住循环就可以控制住任务,即可以控制住线程。while(true){}是永久循环。  控制循环通常使用定义标志来完成。

如果线程处于冻结状态,无法读取标记时,怎样结束线程呢?

利用interrupt()方法,可以将线程从冻结状态强制回到拥有cpu资格的运行状态,但是这种强制动作会抛出异常InterruptedException,需要在catch中进行处理异常。

14.  守护线程:setDaemon(boolean b)方法可以将此线程设置为守护线程或用户线程。Thismethod must be invoked before the thread is started.该方法必须在调用start方法前调用。守护线程与一般线程运行、等待都一样,只不过结束的时候不一样,只要一般线程消失,守护线程会自动消失,无论其处于任何状态。当所有的线程都是守护线程时,此时程序会自动退出。

15.  join()方法:作用:主线程停止,等待调用join方法的线程运行完毕后,再继续执行,注意主线程只等调用join方法的线程运行完毕,调用join方法也会抛出异常。临时加入一个线程可以使用join方法。

16.  setPriority(int newPriority):设置优先级;数值只有1—10;默认的值是5.

17.  想要快速创建一个线程可以利用匿名内部类:

Runnable ru = new Runnable(){


***************public void run(){    }

};

new Thread(ru).start();

 面试题:(1)class 
Test3implements Runnable{
    public
void
run(Thread t) {
} }
请问有没有错误?有错误,错在第几行?
答:有错误,错在第一行,原因:要想实现接口必须实现接口中的所有方法,而接口Runnable的run方法是空参数的,所以此处并没有实现接口中的方法,如果没有实现接口中的方法,那么此类只能定义为抽象类,所以错在第一行,应该声明为abstract
(2)public
class
Test2 {
 
    public
static void
main(String[]
args) {
    new Thread(new Runnable() {
        public
void
run() {
        System.out.println("AAAAAAAA11");//对接口进行匿名内部类
        }
    }) {//Thread作为父类,进行匿名内部类,下面的方法可以覆盖上面的封装了run方法的对象的run方法
        public
void
run() {
        System.out.println("BBBBBBB11");
        }
    }.start(); //分析:一共存在三个run方法:①接口Runnable中的一个抽象的run方法,不可被调用;
    //②Thread类实现了接口Runnable,故实现了其中的run方法,但是没有做任何动作,就是用来被重写的;
    //③对接口进行匿名内部类,即创建一个类实现接口,实现了run方法;
    //④把Thread类作为父类,以匿名内部类的方法创建一个子类,子类中对父类的run方法进行复写。
    //对于子类来说,首先调用子类自己重写的run方法,其次是父类中以参数传递进来的对象的run方法,再其次是父类的run方法。
 
    new Thread(new Runnable() {
    public
void
run() {
       System.out.println("AAAAAAAAAAAA22");
    }
    }) {//子类中并未重写run方法
    }.start();
    new Thread() {
   
    }.start();//调用Thread类自己的run方法,是空的,什么也不执行
}
}

输出结果为:
BBBBBBB11
AAAAAAAAAAAA22
 

18.  多消费者—多生产者:

典型事例:
importjava.util.concurrent.locks.Condition;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
 
public
class
BounderBuffer {
    private
int
putptr,takeptr,count;
    private
final
Lock lock = new ReentrantLock();
    private
final
Condition notFull =
lock.newCondition();
    private
final
Condition notEmpty =
lock.newCondition();
    Object[] items = new Object[20];
    public
void
put(Object duck) {
    lock.lock();
    try {
    while(count ==
items.length)
        try {
        notFull.await();
        } catch (InterruptedException
e) {
        }
    items[putptr] =
duck;
    if(++putptr ==
items.length)
putptr = 0;
    count++;
    System.out.println("put "+Thread.currentThread().getName()+"  putptr = "+putptr
+ " count= "+count );
    notEmpty.signal();
    }
    finally {
        lock.unlock();
    }
   
    }
    public Object take() {
    lock.lock();
    try {
        while(count == 0)
        try{
           notEmpty.await();
        }
        catch(InterruptedException
e) {}
       Object duck =
items[takeptr];
        if(++takeptr ==
items.length)
takeptr = 0;
        count--;
       System.out.println("take "+Thread.currentThread().getName()+"   takeptr = "+takeptr
+ " count= "+count );
        notFull.signal();
        return
duck;
       
    }
    finally {
        lock.unlock();
    }
    }
}
class PutDuck
implements Runnable{
    BounderBuffer b =
null
;
    PutDuck(BounderBuffer bou){
    this.b =
bou;
    }
    private Object
duck = new Object();
    public
void
run() {
    for(int
i = 100;i > 0;i--)
        b.put(duck);
    }
}
class TakeDuck
implements Runnable{
    BounderBuffer bou =
null
;
    TakeDuck(BounderBuffer bou){
    this.bou =
bou;
    }
    private Object
duck = new Object();
    public
void
run() {
    for(int
i = 100;i > 0;i--) {
       duck =
bou.take();
    }
    }
   
}
class Test{
    public
static void
main(String[]
args) {
    BounderBuffer b =
new
BounderBuffer();
    PutDuck p = new PutDuck(b);
    TakeDuck t = new TakeDuck(b);
    Thread t0 = new Thread(p);
    Thread t1 = new Thread(p);
    Thread t2 = new Thread(p);
    Thread t3 = new Thread(t);
    Thread t4 = new Thread(t);
    Thread t5 = new Thread(t);
    t0.start();
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();
    }
}
 
 

Java中线程间通信

1.      线程间通信(通讯): 多个线程在处理同一个资源,但任务不同。

一、等待/唤醒机制:

1.  涉及的方法:

(1) wait(); 使线程处于冻结状态,被wait的线程会存储到线程池(等待集)中;

(2) notify(); 唤醒线程池中的一个线程,这个线程是任意的;

(3) notifyAll(); 唤醒线程池中的所有线程。

2.  这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法;而且必须要明确到底操作的是哪个锁上的线程。即必须明确线程由那个监视器监视。

3.  监视器: 就是所说的锁。

4. 为什么操作线程的方法wait()、notify()、notifyAll()定义在了Object类中?

答:因为这些方法就是监视器的方法,监视器就是锁,锁可以是任意的对象,如Object obj = new Object();既然可以是任意对象,那么这些方法需要定义在最高的类中,即定义在Object类中。

5.     线程间通信的示例:

//创建一个资源类,存放资源
class Resource {

    private String
name;
    private String
sex;
    private
boolean
flag = false;
    public
synchronized void
input(String
name, String sex) {
    if (flag)
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
    this.name =
name;
    this.sex =
sex;
    flag = true;
    this.notify();
    }
 
    public
synchronized void
output() {
    if (!flag)
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
    System.out.println(name +
" 的性别:   " +
sex);
    flag = false;
    this.notify();
    }
}
//创建输入的run方法,利用类对任务进行封装
class Input
implements
Runnable {
    Resource r = null;
 
    Input(Resource r) {
    this.r =
r;
    }
 
    public
void
run() {
    int
x = 0;
    for (int
i = 10; i > 0;
i--) {
        if (x == 0)
        r.input("KangKang",
"男");
        else
        r.input("Jane",
"女");
        x = (x + 1) % 2;
    }
    }
 
}
//利用类实现对输出任务的封装
class Output
implements
Runnable {
    Resource r = null;
    Output(Resource r) {
    this.r =
r;
    }
    public
void
run() {
    for (int
i = 10; i > 0;
i--)
        r.output();
    }
}
//主方法所在的类
public
class
ThreadCommunication {
 
    public
static void
main(String[]
args) {
    Resource r = new Resource();//创建一个资源对象,使下面两个线程同时操作同一个资源对象
    Input in = new Input(r);
    Output out = new Output(r);
    Thread tin = new Thread(in);
    Thread tout = new Thread(out);
    tin.start();
    tout.start();
    }
}

结果:(实现一次赋值,一次输出,两个线程交替进行)
KangKang的性别:   男
Jane 的性别:   女
KangKang的性别:   男
Jane 的性别:   女
KangKang的性别:   男
Jane 的性别:   女
KangKang的性别:   男
Jane 的性别:   女
KangKang的性别:   男
Jane 的性别:   女
6.     生产者—消费者模式:

(1)单生产者—单消费者模式:

class Resource1 {
    private
int
count = 0;//
生产物品编号
    private String
name;
    private
boolean
flag = false;
 
    public
synchronized void
produce(Stringname) {
     
    this.name =
name;
    if (flag)
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
    this.count++;
    System.out.println("生产的 " +
this.name +
"  的编号是: " +
count);
    flag = true;
    this.notify();
    }
 
    public
synchronized void
eat() {
    if (!flag)

        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
     System.out.println("消费者吃掉的   " +
this.name +
"  的编号是: "
           + this.count);
     flag = false;
        this.notify();
    }
}
 
class Producer
implements Runnable {
    private Resource1
r = null;
 
    Producer(Resource1 r) {
    this.r =
r;
    }
 
    public
void
run() {
    for (int
i = 100; i > 0;
i--) {
        r.produce("烤鸭");
    }
    }
 
}
 
class Consumer
implements Runnable {
    private Resource1
r = null;
 
    Consumer(Resource1 r) {
    this.r =
r;
    }
 
    public
void
run() {
    for (int
i = 100; i > 0;
i--)
        r.eat();
    }
}
 
public
class
ProducerConsumerDemo {
    public
static void
main(String[]
args) {
    Resource1 r = new Resource1();
    Producer p = new Producer(r);
    Consumer c = new Consumer(r);
    Thread tp = new Thread(p);
    Thread tc = new Thread(c);
    tp.start();
    tc.start();
    }
}
 

(2)多生产者—多消费者模式:

①    将if换成while,解决了线程获取执行权后,再次判断flag,决定是否执行;if只能判断一次,判断后如果满足if句则线程wait,等到唤醒后直接执行下面的代码,不再判断;利用while可以解决这个问题,因为while是如果一直 为真,则一直循环,知道不满足才会执行下面的代码。While + notify会导致程序死锁。

②    notifyAll解决了保证能够唤醒对方的线程,而notify只可以唤醒一个线程,可能仍然把本方的线程唤醒,然后本方判断flag不能跳出,导致所有的线程都冻结,产生死锁。

class Resource1 {
    private
int
count = 0;//
生产物品编号
    private String
name;
    private
boolean
flag = false;
    public
synchronized void
produce(Stringname) {
    this.name =
name;
    while (flag) //修改:将if换成while
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
    this.count++;
    System.out.println(Thread.currentThread().getName()+"生产的 " +
this.name +
"  的编号是: " +
count);
    flag = true;
    this.notifyAll();//将notify
换成 notifyAll
    }
 
    public
synchronized void
eat() {
    while(!flag)
//修改:将if换成while
        try {
        this.wait();
        } catch (InterruptedException
e) {
        }
     System.out.println(Thread.currentThread().getName()+"消费者吃掉的   "
+ this.name +
"  的编号是: "
           + this.count);
     flag = false;
        this.notifyAll();//将notify
换成 notifyAll
    }
}
 
class Producer
implements Runnable {
    private Resource1
r = null;
 
    Producer(Resource1 r) {
    this.r =
r;
    }
 
    public
void
run() {
    for (int
i = 100; i > 0;
i--) {
        r.produce("烤鸭");
    }
    }
}
 
class Consumer
implements Runnable {
    private Resource1
r = null;
 
    Consumer(Resource1 r) {
    this.r =
r;
    }
 
    public
void
run() {
    for (int
i = 100; i > 0;
i--)
        r.eat();
    }
}
 
public
class
MultiProducerConsumerDemo {
    public
static void
main(String[]
args) {
    Resource1 r = new Resource1();
    Producer p = new Producer(r);
    Producer p1 = new Producer(r);
    Consumer c = new Consumer(r);
    Consumer c1 = new Consumer(r);
    Thread t0 = new Thread(p);
    Thread t1 = new Thread(p1);
    Thread t2 = new Thread(c);
    Thread t3 = new Thread(c1);
    t0.start();
    t1.start();
    t2.start();
    t3.start();
    }
}

7.     Lock接口:的出现替代了同步代码块或者同步方法;将同步的隐式锁操作变成了显式的锁操作,变得更加灵活,并且可以在一个锁上设置多个监视器。Xxx.lock();方法获取锁,unlock();释放锁,通常将xxx.unlock();放在finally语句中。


8.     Condition接口:的出现替代了Object类中的wait、notify、notifyAll方法,将这些监视器方法单独进行了封装,变成Condition监视器对象,可以和任意锁进行组合使用,方法变成await、signal、signalAll。

 

9.     同步代码块:对于锁的操作是隐式的。自从JDK1.5,Lock便取代了synchronized。

·        标准形式:

·        
Lock l = ...;

·        
 l.lock();

·        
 try {

·        
   // access the resource protected by this lock

·        
 } finally {

·        
   l.unlock();

 }


10.  Sleep() 方法和wait() 方法 有什么区别?

答:

(1)Wait可以指定时间,也可以不指定时间,sleep必须指定时间;

(2)在同步中时,对于CPU的执行权和锁的处理不同:wait释放CPU执行权,释放锁,sleep释放CPU执行权,不释放锁(sleep不需要别人叫,wait需要别人叫,所以要释放锁)。

11.  在一个同步中,只能有一个线程执行,但是 可以在一个线程中被唤醒着多个线程,只有获得此同步锁的线程才会执行,被唤醒的其他线程且不具有锁的线程不会执行。

12.  线程停止的方法:①run方法结束;②stop方法。

13.  怎么控制线程的任务结束呢?

答:任务中设置有循环结构,只要控制住循环就可以控制住任务,即可以控制住线程。while(true){}是永久循环。  控制循环通常使用定义标志来完成。

如果线程处于冻结状态,无法读取标记时,怎样结束线程呢?

利用interrupt()方法,可以将线程从冻结状态强制回到拥有cpu资格的运行状态,但是这种强制动作会抛出异常InterruptedException,需要在catch中进行处理异常。

14.  守护线程:setDaemon(boolean b)方法可以将此线程设置为守护线程或用户线程。Thismethod must be invoked before the thread is started.该方法必须在调用start方法前调用。守护线程与一般线程运行、等待都一样,只不过结束的时候不一样,只要一般线程消失,守护线程会自动消失,无论其处于任何状态。当所有的线程都是守护线程时,此时程序会自动退出。

15.  join()方法:作用:主线程停止,等待调用join方法的线程运行完毕后,再继续执行,注意主线程只等调用join方法的线程运行完毕,调用join方法也会抛出异常。临时加入一个线程可以使用join方法。

16.  setPriority(int newPriority):设置优先级;数值只有1—10;默认的值是5.

17.  想要快速创建一个线程可以利用匿名内部类:

Runnable ru = new Runnable(){


***************public void run(){    }

};

new Thread(ru).start();

 面试题:(1)class 
Test3implements Runnable{
    public
void
run(Thread t) {
} }
请问有没有错误?有错误,错在第几行?
答:有错误,错在第一行,原因:要想实现接口必须实现接口中的所有方法,而接口Runnable的run方法是空参数的,所以此处并没有实现接口中的方法,如果没有实现接口中的方法,那么此类只能定义为抽象类,所以错在第一行,应该声明为abstract
(2)public
class
Test2 {
 
    public
static void
main(String[]
args) {
    new Thread(new Runnable() {
        public
void
run() {
        System.out.println("AAAAAAAA11");//对接口进行匿名内部类
        }
    }) {//Thread作为父类,进行匿名内部类,下面的方法可以覆盖上面的封装了run方法的对象的run方法
        public
void
run() {
        System.out.println("BBBBBBB11");
        }
    }.start(); //分析:一共存在三个run方法:①接口Runnable中的一个抽象的run方法,不可被调用;
    //②Thread类实现了接口Runnable,故实现了其中的run方法,但是没有做任何动作,就是用来被重写的;
    //③对接口进行匿名内部类,即创建一个类实现接口,实现了run方法;
    //④把Thread类作为父类,以匿名内部类的方法创建一个子类,子类中对父类的run方法进行复写。
    //对于子类来说,首先调用子类自己重写的run方法,其次是父类中以参数传递进来的对象的run方法,再其次是父类的run方法。
 
    new Thread(new Runnable() {
    public
void
run() {
       System.out.println("AAAAAAAAAAAA22");
    }
    }) {//子类中并未重写run方法
    }.start();
    new Thread() {
   
    }.start();//调用Thread类自己的run方法,是空的,什么也不执行
}
}

输出结果为:
BBBBBBB11
AAAAAAAAAAAA22
 

18.  多消费者—多生产者:

典型事例:
importjava.util.concurrent.locks.Condition;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
 
public
class
BounderBuffer {
    private
int
putptr,takeptr,count;
    private
final
Lock lock = new ReentrantLock();
    private
final
Condition notFull =
lock.newCondition();
    private
final
Condition notEmpty =
lock.newCondition();
    Object[] items = new Object[20];
    public
void
put(Object duck) {
    lock.lock();
    try {
    while(count ==
items.length)
        try {
        notFull.await();
        } catch (InterruptedException
e) {
        }
    items[putptr] =
duck;
    if(++putptr ==
items.length)
putptr = 0;
    count++;
    System.out.println("put "+Thread.currentThread().getName()+"  putptr = "+putptr
+ " count= "+count );
    notEmpty.signal();
    }
    finally {
        lock.unlock();
    }
   
    }
    public Object take() {
    lock.lock();
    try {
        while(count == 0)
        try{
           notEmpty.await();
        }
        catch(InterruptedException
e) {}
       Object duck =
items[takeptr];
        if(++takeptr ==
items.length)
takeptr = 0;
        count--;
       System.out.println("take "+Thread.currentThread().getName()+"   takeptr = "+takeptr
+ " count= "+count );
        notFull.signal();
        return
duck;
       
    }
    finally {
        lock.unlock();
    }
    }
}
class PutDuck
implements Runnable{
    BounderBuffer b =
null
;
    PutDuck(BounderBuffer bou){
    this.b =
bou;
    }
    private Object
duck = new Object();
    public
void
run() {
    for(int
i = 100;i > 0;i--)
        b.put(duck);
    }
}
class TakeDuck
implements Runnable{
    BounderBuffer bou =
null
;
    TakeDuck(BounderBuffer bou){
    this.bou =
bou;
    }
    private Object
duck = new Object();
    public
void
run() {
    for(int
i = 100;i > 0;i--) {
       duck =
bou.take();
    }
    }
   
}
class Test{
    public
static void
main(String[]
args) {
    BounderBuffer b =
new
BounderBuffer();
    PutDuck p = new PutDuck(b);
    TakeDuck t = new TakeDuck(b);
    Thread t0 = new Thread(p);
    Thread t1 = new Thread(p);
    Thread t2 = new Thread(p);
    Thread t3 = new Thread(t);
    Thread t4 = new Thread(t);
    Thread t5 = new Thread(t);
    t0.start();
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();
    }
}
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: