14多线程

线程间通讯:

多个线程在处理同一资源,但是任务却不同.

//资源
class Resource
{
    String name;
    String sex;
}

//输入
class Input implements Runnable
{
    Resource r;
    Input(Resource r)
    {
        this.r = r;
    }
    public void run()
    {
        int x=0;
        while(true)
        {
            synchronized(r)
            {    
                if(x==0)
                {
                    r.name="mike";
                    r.sex="nan";
                }
                else
                {
                    r.name="丽丽";
                    r.sex="女女女女";
                }
                x=(x+1)%2;
            }
        }
    }
}


//输出
class Output implements Runnable
{
    Resource r;
    Output(Resource r)
    {
        this.r = r;
    }
    public void run()
    {
        
        while(true)
        {
            synchronized(r)
            {
                System.out.println(r.name+"..."+r.sex);
            }
        }
    }
}

class Demo
{
    public static void main(String[] args)
    {
        //创建资源
       Resource r = new Resource();
       //创建任务
       Input in = new Input(r);
       Output out = new Output(r);
        //创建线程,执行路径.
       Thread t1 = new Thread(in);
       Thread t2 = new Thread(out);
        //开启线程
       t1.start();
       t2.start();

    }
}

 等待/唤醒机制:

涉及的方法:
1.wait():让线程处于冻结状态.被wait的线程会被存储到线程池中.

2.notify():唤醒线程池中的一个线程(任意).

3.notifyAll():唤醒线程池中的所有线程.

这些方法都必须定义在同步中.

因为这些方法是用于操作线程状态的方法.

必须要明确到底操作的是哪个锁上的线程.

为什么操作线程的方法wait,notify,notifyAll定义在了Object类中.

因为这些方法是监视器的方法,监视器其实就是锁.

锁可以是任意的对象,任意的对象调用的方法一定定义在Object类中.

//资源
class Resource
{
    private String name;
    private String sex;
    private boolean flag = false;

    public synchronized void set(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 out()
    {
        if(!flag)
                try{
                        this.wait();
                    }
                    catch(InterruptedException e){}
        System.out.println(name+"..."+sex);
        flag=false;
        this.notify();
    }
}

//输入
class Input implements Runnable
{
    Resource r;
    Input(Resource r)
    {
        this.r = r;
    }
    public void run()
    {
        int x=0;
        while(true)
        {
                
                if(x==0)
                {
                    r.set("mike","man");
                }
                else
                {
                    r.set("lili","女");
                }
                x=(x+1)%2;        
        }
    }
}


//输出
class Output implements Runnable
{
    Resource r;
    Output(Resource r)
    {
        this.r = r;
    }
    public void run()
    {
        
        while(true)
        {
            r.out();
        }
    }
}

class Demo
{
    public static void main(String[] args)
    {
        //创建资源
       Resource r = new Resource();
       //创建任务
       Input in = new Input(r);
       Output out = new Output(r);
        //创建线程,执行路径.
       Thread t1 = new Thread(in);
       Thread t2 = new Thread(out);
        //开启线程
       t1.start();
       t2.start();

    }
}

 

class Resource
{
    private String name;
    private int count=1;
    private boolean flag = false;

    public synchronized void set(String name)
    {
        while(flag)
            try{this.wait();}catch(InterruptedException e){}
        this.name=name + count;
        count++;
        System.out.println(Thread.currentThread().getName()+"..生产者.."+this.name);
        flag=true;
        notifyAll();
    }
    
    public synchronized void out()
    {
        while(!flag)
            try{this.wait();}catch(InterruptedException e){}
        System.out.println(Thread.currentThread().getName()+"..消费者.."+this.name);
        flag=false;
        notifyAll();
    }
}

class Producer implements Runnable
{
    private Resource r;
    Producer(Resource r)
    {
        this.r=r;
    }
    public void run()
    {
        while(true)
        {
            r.set("烤鸭");
        }
    
    }
}

class Consumer implements Runnable
{
    private Resource r;
    Consumer(Resource r)
    {
        this.r=r;
    }
    public void run()
    {
        while(true)
        {
            r.out();
        }
    }

}



class Demo
{
    public static void main(String[] args)
    {
        Resource r =new Resource();
        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);

        Thread t0 = new Thread(pro);
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(con);
        Thread t3 = new Thread(con);
        
        t0.start();
        t1.start();
        t2.start();
        t3.start();

    }
}

if判断标记,只有一次,回导致不该运行的线程运行了,出现了数据错误的情况.

while判断标记,解决了线程获取执行权后,是否要运行.

notify只能唤醒一个线程,如果本方唤醒了本方,没有意义.而且while判断标记,加notify会导致死锁.

notifyAll解决了,本方线程一定会唤醒对方线程的问题.

 

同步代码块,对于锁的操作是隐式的.

若code...中throw Exception();锁将不能释放.

故应将lock.unlock()放在finally中.一定要释放.

 

lock l = ...;

l.lock();

try{
}

finally{

l.unlock();

}

import java.util.concurrent.locks.*;

class Resource
{
    private String name;
    private int count=1;
    private boolean flag = false;
    
    //创建一个锁对象
    Lock lock = new ReentrantLock();
    
    //通过已有的锁获得该锁上的监视器对象.
    //Condition con = lock.newCondition();
    //通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者.
    Condition producer_con = lock.newCondition();
    Condition consumer_con = lock.newCondition();

    public void set(String name)
    {
        lock.lock();
        try
        {
            while(flag)
            try{producer_con.await();}catch(InterruptedException e){}
            this.name=name + count;
            count++;
            System.out.println(Thread.currentThread().getName()+"..生产者.."+this.name);
            flag=true;
            //notifyAll();
            //con.signalAll();
            consumer_con.signal();
        }
        finally
        {
            lock.unlock();
        }
        

    }
    
    public void out()
    {
        lock.lock();
        try
        {
            while(!flag)
            try{consumer_con.await();}catch(InterruptedException e){}
            System.out.println(Thread.currentThread().getName()+"..消费者.."+this.name);
            flag=false;
            //notifyAll();
            //con.signalAll();
            producer_con.signal();
        }
        finally
        {
            lock.unlock();
        }
    }
}

class Producer implements Runnable
{
    private Resource r;
    Producer(Resource r)
    {
        this.r=r;
    }
    public void run()
    {
        while(true)
        {
            r.set("烤鸭");
        }
    
    }
}

class Consumer implements Runnable
{
    private Resource r;
    Consumer(Resource r)
    {
        this.r=r;
    }
    public void run()
    {
        while(true)
        {
            r.out();
        }
    }

}



class Demo
{
    public static void main(String[] args)
    {
        Resource r =new Resource();
        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);

        Thread t0 = new Thread(pro);
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(con);
        Thread t3 = new Thread(con);
        
        t0.start();
        t1.start();
        t2.start();
        t3.start();

    }
}

Lock接口:出现替代了同步代码块或者同步函数.

将同步的隐式锁操作变成了显示锁操作.

同时更为灵活,可以一个锁上加上多组监视器.

lock():获取锁.unlock():释放锁,通常需要定义在finally代码块中.

Condition接口:出现替代了Object中的wait notify notifyAll方法,

将这些监视器方法单独进行了封装,变成了Condition监视器对象,

可以任意锁进行组合.

await();

signal();

signalAll();

 

wait和sleep的区别:

 1.wait可以指定时间,也可以不指定.

    而sleep必须指定时间.

2.在同步中时,对于cpu的执行权和锁的处理不同.

wait:释放执行权,释放锁.

sleep:释放执行权,不释放锁.

 

停止线程:

1.stop方法.

 2.run方法结束.

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

任务中都会有循环结构,只要控制住循环就可以结束任务.

控制循环通常就用定义标记来完成.

但是如果线程处于了冻结状态,无法读取标记,该如何结束呢?

可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中来,让线程具备

cpu的执行资格.

但是强制动作会发生InterruptedException,记得要处理.

 

posted on 2016-12-19 23:30  夜行锦衣  阅读(95)  评论(0编辑  收藏  举报

导航