多线程2

线程间通信
在这里插入图片描述
线程间通信–等待唤醒机制

/**
 * 线程间通信:
 * 多个线程在处理同一资源,但是任务却不同
 */

 //等待唤醒机制 
 //设计的方法:
 //1.wait();让线程处于冻结状态(线程释放cpu执行权,被wait的线程会存放在线程池中)
 //2.notify();唤醒线程池中的一个线程(任意)
 //3.notifyAll();唤醒线程池中所有线程

 //这些方法必须定义在同步中,因为这些方法是用于操作线程的方法,必须要明确到底操作的是哪个锁上的线程

 //为什么操作线程的方法wait(),notify,notifyAll定义在了Object类中,
 //因为这些方法是监视器的方法。监视器其实就是锁。
 //锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。

//资源
class Resource{
    String name;
    String sex;
    Boolean flag = false;
}
//输入
class Input implements Runnable{
    Resource r;
    Input(Resource r){
        this.r = r;
    }
    public void run(){
        int x = 0;
        while(true){
            synchronized(r){
                if(r.flag)
                    try {
                        r.wait();
                    } catch (Exception e) {
                        //TODO: handle exception
                    }
                if(x==0){
                    this.r.name = "zxy";
                    this.r.sex = "man";
                }
                else{
                    this.r.name = "康萍萍";
                    this.r.sex = "女";
                }
                r.flag = true;
                r.notify();
            }
            x = (x+1)%2;
        }
    }
}
//输出
class Output implements Runnable{
    Resource r;
    Output(Resource r){
        this.r = r;
    }
    public void run(){
        while(true){
            synchronized(r){
                if(!r.flag)
                    try {
                        r.wait();
                    } catch (Exception e) {
                        //TODO: handle exception
                    } 
                System.out.println(this.r.name+"..."+this.r.sex);
                r.flag = false;
                r.notify();
            }
        }
    }
}

class MyLock{
    public static Object locka = new Object();
    public static Object lockb = new Object();
}
public class packDemo{
    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 String sex;
    private Boolean flag = false;
    public synchronized void set(String name,String sex){
        if(this.flag)
            try {this.wait();} catch (Exception e) {}
        this.name = name;
        this.sex = sex;
        this.flag = true;
        this.notify();
    }
    public synchronized void show(){
        if(!this.flag)
            try {this.wait();} catch (Exception e) {}
        System.out.println(name+"......"+sex);
        this.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("zxy", "man");
            }
            else{
                r.set("康萍萍", "女");
            }
            x = (x+1)%2;
        }
    }
}
//输出
class Output implements Runnable{
    Resource r;
    Output(Resource r){
        this.r = r;
    }
    public void run(){
        while(true){
            r.show();
        }
    }
}

class MyLock{
    public static Object locka = new Object();
    public static Object lockb = new Object();
}
public class packDemo{
    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();
    }
}

线程间通信–多生产者多消费者问题

/**
 * 生产者,消费者
 * 多生产者,多消费者
 * if判断标记,只有一次,会导致不该运行的线程运行了,出现数据错误的情况
 * while判断标记,解决了线程获取执行权后,是否要运行
 * notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记加notify会导致死锁。
 * notifyAll解决了本方线程一定会唤醒对方线程的问题。
 */
class Resources{
    private String name;
    private int count = 1;
    private Boolean flag = false;
    public synchronized void set(String name){
        while(flag)//为了让多个生产者线程在wait醒来之后再次检测flag,将if改为while
            try {this.wait();} catch (Exception e) {}
        this.name = name+count;
        count++;
        System.out.println(Thread.currentThread().getName()+"...生产者..."+name);
        flag = true;
        notifyAll();
    }
    public synchronized void out(){
        while(!flag)
            try {this.wait();} catch (Exception e) {}
        System.out.println(Thread.currentThread().getName()+"...消费者..."+name);
        flag = false;
        notifyAll();
    }
}
class Producer implements Runnable{
    private Resources r;
    Producer(Resources r){
        this.r = r;
    }
    public void run(){
        while(true){
            r.set("kaoya");
        }
    }
}
class Consumer implements Runnable{
    private Resources r;
    Consumer(Resources r){
        this.r = r;
    }
    public void run(){
        while(true){
            r.out();
        }
    }
}
public class packDemo{
    public static void main(String[] args){
        Resources r = new Resources();
        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(pro);
        Thread t3 = new Thread(con);
        Thread t4 = new Thread(con);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

在这里插入图片描述

//Lock接口:出现替代了同步代码块和同步函数。将同步的隐式锁操作变成了显示锁操作,同时一个锁可以加多个监视器
//lock方法获取锁,unlock方法释放锁(通常需要定义在finally代码块中)
//Condition接口:出现替代了Object中的wait,notify,notifyAll方法。
                // 将这些监视器方法单独进行了封装,变成Condition监视器对象。
                // 可以与任意锁进行组合
                // await();
                // signal();
                // signalAll();

JDK1.5替代之后,上面代码可更新为

import java.util.concurrent.locks.*;

class Resources{
    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)//为了让多个生产者线程在wait醒来之后再次检测flag,将if改为while
            //try {this.wait();} catch (Exception e) {}
                try {//con.await();
                    producer_con.await();
                } catch (Exception e) {}
            this.name = name+count;
            count++;
            System.out.println(Thread.currentThread().getName()+"...生产者..."+name);
            flag = true;
            //notifyAll();
            // con.signalAll();
            consumer_con.signal();
        }
        finally{
            lock.unlock();
        }
    }
    public void out(){
        lock.lock();
        try{
            while(!flag)
            //try {this.wait();} catch (Exception e) {}
                try {//con.await();
                    consumer_con.await();
                } catch (Exception e) {}
            System.out.println(Thread.currentThread().getName()+"...消费者..."+name);
            flag = false;
            //notifyAll();
            // con.signalAll();
            producer_con.signal();
        }
        finally{
            lock.unlock();
        }
    }
}
class Producer implements Runnable{
    private Resources r;
    Producer(Resources r){
        this.r = r;
    }
    public void run(){
        while(true){
            r.set("kaoya");
        }
    }
}
class Consumer implements Runnable{
    private Resources r;
    Consumer(Resources r){
        this.r = r;
    }
    public void run(){
        while(true){
            r.out();
        }
    }
}
public class packDemo{
    public static void main(String[] args){
        Resources r = new Resources();
        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(pro);
        Thread t3 = new Thread(con);
        Thread t4 = new Thread(con);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

线程间通信–wait和sleep的区别

// wait和sleep的区别?
// 1.wait可以指定时间也可以不指定。
//     sleep必须指定时间
// 2.在同步中时,对cpu的执行权和锁的处理不同
//     wait 释放执行权,释放锁
//     sleep 释放执行权,不释放锁

线程间通信–停止线程方式interrupt

/*
停止线程:
1.stop方法
2.run方法结束
怎么控制线程的任务结束呢?
    1.任务中都会有循环结构,只要控制住循环就可以结束任务。
    控制循环通常就用定义标记来完成。
    2.可以使用interrupt将线程从冻结强制恢复到运行状态中来,让线程具备cpu的执行资格
    但是强制动作会发生中断异常,记得处理
setDaemon()
*/
class StopThread implements Runnable{
    private Boolean flag = true;
    public void run(){
        while(flag){
            try{
                wait();
            }
            catch(InterruptedException e){
                System.out.println(Thread.currentThread().getName()+"......"+e);
                flag = false;
            }
            System.out.println(Thread.currentThread().getName()+"+++++");
        }
    }
    public void setFlag(){
        flag = false;
    }
}

public class packDemo{
    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++==50){
                // st.setFlag();
                t1.interrupt();//可以使用interrupt将线程从冻结强制恢复到运行状态中来
                                //让线程具备cpu的执行资格
                t2.interrupt();
                break;
            }
            System.out.println("main....."+num);
        }
    }
}

线程间通信–守护线程setDaemon
多线程其他方法

//thread.join()//等待该线程终止
//Thread.yield();//释放执行权,让其他线程有机会
//Thread.setPriority(Thread.MAX_PRIORITY);//改变优先级

class Demo implements Runnable{
    public void run(){
        for(int x=0;x<50;x++){
            System.out.println(Thread.currentThread().getName()+"++++++"+x);
            
        }
    }
}
public class packDemo{
    public static void main(String[] args) throws Exception{
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        //t1.join();//t1线程要申请加入进来,运行
        t2.start();
        t2.setPriority(Thread.MAX_PRIORITY);
        for(int i=0;i<50;i++){
            // System.out.println(Thread.currentThread().getName()+"...main..."+i);
        }
        // System.out.println("hello");
    }
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页