首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

生产者与消费者有关问题 线程基础篇

2012-10-13 
生产者与消费者问题线程基础篇线程常涉及的若干方法Objectnotify()//唤醒在此对象监视器上等待的单个线程n

生产者与消费者问题 线程基础篇
线程常涉及的若干方法
Object
        notify()//唤醒在此对象监视器上等待的单个线程
        notifyAll()//唤醒在此对象监视器上所有等待的所有线程
        wait() //导致当前线程等待,由notify(),notifyAll()唤醒
Thread
        Thread()
        Thread(Runable target)
        Thread(Runable target, String name)
        currentThread()         //返回当前正在执行的线程对象的引用
        getId()//返回该线程的线程号
        getName()//返回该线程的名称
        interrupt()//中断线程
        interrupted()        //测试该线程是否已经中断 静态方法
        isAlive()//测试该线程是否处于活动状态
        isInterrupted()  //测试该线程是否已经中断
        join()//等待该线程终止
        sleep()//睡眠
        start()//启动线程
        yield()//暂停当前正在执行的线程对象,并执行其他线程 静态方法
Runnable
        run()

创建线程

public class ThreadTest extends Thread {    public void run() {        System.out.println("@run() 子线程号:" + Thread.currentThread().getId());        for(int i=0; i<5; i++)            System.out.println("i=" + i);    }           public static void main(String[] args) {        ThreadTest tt = new ThreadTest();        tt.start();        System.out.println("@main() 主程序的线程号:" + Thread.currentThread().getId());    }}


public class RunnableTest implements Runnable {    public void run() {        System.out.println("@run() 子线程号:" + Thread.currentThread().getId());        for(int i=0; i<5; i++)            System.out.println("i=" + i);    }    public static void main(String[] args) {        Thread t = new Thread(new RunnableTest());        t.start();        System.out.println("@main() 主程序的线程号:" + Thread.currentThread().getId());    }}



线程并发控制带来的问题
两个以上线程并发访问共享变量,假设线程A取数据,线程B修改数据,
那么A取得数据可能已经被B修改过,所以需要对共享变量进行控制

多线程同步的原理
共享变量为类的属性,所以JVM通过给每个对象加锁实现多线程的同步处理。
对象A包括实例对象和类对象
实例对象 A a = new A();
类对象  a.getClass()  Class.forName("a")   A.class
一个类对应一个类对象,类对象在要使用类的时候加载,A.java编译生成A.class,将A.class加载到内存就是类对象
类对象具体参考:
http://www.iteye.com/topic/355046

JVM为每个对象配置一把锁(lock)和一个等候集(wait set)。
对象内部锁定只同步语句块和同步方法,一锁则全锁 (全部同步语句块和同步方法
asynchronized(asyncObject) {}
public asynchronized void print() {}
JVM上锁:
       1.判断上锁对象类型
            1.1 实例对象,锁定所有非静态同步方法和同步语句块
                public asynchronized void print()
            1.2 类对象,锁定所有静态同步方法和同步语句块
                public static asynchronized void print()

import java.util.Date;class AsyncObj {    public synchronized static void asyncStatic1() throws InterruptedException {        System.out.println("进入asyncStatic1    " + new Date());        Thread.sleep(2000);        System.out.println("离开asyncStatic1    " + new Date());    }    public synchronized static void asyncStatic2() throws InterruptedException {        System.out.println("进入asyncStatic2    " + new Date());        Thread.sleep(2000);        System.out.println("离开asyncStatic2    " + new Date());    }    public synchronized void async1() throws InterruptedException {        System.out.println("进入async1    " + new Date());        Thread.sleep(2000);        System.out.println("离开async1    " + new Date());    }    public synchronized void async2() throws InterruptedException {        System.out.println("进入async2    " + new Date());        Thread.sleep(2000);        System.out.println("离开async2    " + new Date());    }        public void nonAsync() throws InterruptedException {        Thread.sleep(1000);        System.out.println("进入nonAsync    " + new Date());        System.out.println("离开nonAsync    " + new Date());    }        public static void nonAsyncStatic() throws InterruptedException {        Thread.sleep(1000);        System.out.println("进入nonAsyncStatic    " + new Date());        System.out.println("离开nonAsyncStatic    " + new Date());    }}public class AsyncTest extends Thread {    public AsyncObj sharedObj;    public int asyncTestThreadId;    public AsyncTest(int asyncTestThreadId, AsyncObj sharedObj) {        this.sharedObj = sharedObj;        this.asyncTestThreadId = asyncTestThreadId;    }    public void run() {        try {            switch(asyncTestThreadId) {            case 0:                sharedObj.async1();     //锁定实例对象                break;            case 1:                sharedObj.async2();                break;            case 2:                sharedObj.nonAsync();                break;            case 3:                AsyncObj.asyncStatic1();  //锁定类对象                break;            case 4:                AsyncObj.asyncStatic2();                break;            case 5:                AsyncObj.nonAsyncStatic();                break;            }        } catch (InterruptedException e) {            e.printStackTrace();        }    }    public static void main(String[] args) {        AsyncObj sharedObj = new AsyncObj(); // 被访问的实例对象        AsyncTest[] threads = new AsyncTest[6]; // 多个访问线程        for (int i = 0; i < 6; i++) {            threads[i] = new AsyncTest(i, sharedObj);            threads[i].start();        }    }}




程序运行:
t=0
asyncStatic1获得类对象的锁睡两秒钟
async1获得实例对象的锁睡两秒钟
t=1
nonAsyncStatic,nonAsync睡醒执行,无所畏惧,锁不住它们
t=2
asyncStatic1,async1睡醒执行完代码退出,释放相应的锁
asyncStatic2,async2获得锁进入
t=4
asyncStatic2,async2睡醒执行完代码退出,释放相应的锁


//消费者与生产者例子介绍 wait(),notify(),notifyAll()//wait(),notify(),notifyAll()只能在同步方法或同步控制块中调用class Disk {    private int apple; // number=1 有苹果 number=0 无苹果        public Disk(int apple) {        this.apple = apple;    }        //消费者调用消费苹果    public synchronized void takeApple() {        String name = Thread.currentThread().getName() + "线程: ";        if (apple == 0)            try {                System.out.println(name + "盘子里面的苹果为空,等待生产者生产");                wait();                 //消费者释放锁,使生产者能够进入addApple()            } catch (InterruptedException e) {                e.printStackTrace();            }        System.out.println(name + "盘子为满,开始消费一个苹果 花费5秒");        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(name + "盘子为满,结束消费一个苹果");        apple--;        System.out.println(name + "唤醒生产者");        notifyAll();    }    //生产者调用生产苹果    public synchronized void addApple() {        String name = Thread.currentThread().getName() + "线程: ";        if (apple == 1)            try {                System.out.println(name + "盘子为满,等待消费者消费");                wait();             //生产者释放锁,使消费者能够进入takeApple()            } catch (InterruptedException e) {                e.printStackTrace();            }        System.out.println(name + "盘子为空,开始生产一个苹果 花费3秒");        try {            Thread.sleep(3000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(name + "盘子为空,结束生产一个苹果");        apple++;        System.out.println(name + "唤醒消费者");        notifyAll();    }}class Producer implements Runnable {    private Disk d;    public Producer(Disk d) {        this.d = d;    }    public void run() {        while (true) {            d.addApple();        }    }}class Consumer implements Runnable {    private Disk d;    public Consumer(Disk d) {        this.d = d;    }    public void run() {        while (true) {            d.takeApple();        }    }}public class TestPC {    public static void main(String[] args) {        Disk d = new Disk(0);   //初始化盘子为0个苹果        new Thread(new Consumer(d),"Consumer").start();     //启动消费者线程        new Thread(new Producer(d),"Producer").start();     //启动生产者线程    }}

同步情况下
sleep()   使当前线程暂停执行一段时间,不释放对象锁,其他线程仍旧无法访问共享变量
wait()    使当前线程暂停执行,释放对象锁标志,该线程被置于等候集,notify()notifyAll(),或者等待超时,激活线程进入就绪态,执行从wait()下一句开始
yield()   作用同sleep()类似,无法指定睡眠时间





热点排行