【Java】【基础篇】day12:线程安全与同步机制

前言

本期任务:毕向东老师Java视频教程学习笔记(共计25天)


代码

/*
需求:输入方保存一个人,输出方打印一个人,交替执行

线程间通讯:
其实就是多个线程在操作同一个资源,
但是操作的动作不同。

*/

//notifyAll();

/*
wait:
notify();
notifyAll();

都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。

也就是说,等待和唤醒必须是同一个锁。

而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。


*/

package day12;

class Resourse1 {
    String name;
    String sex;
    boolean flag = false; // 默认当前无资源
}


class Input implements Runnable {
    private Resourse1 r;

    Input(Resourse1 r) {
        this.r = r;
    }

    public void run() {
        int x = 0;
        while (true) {
            synchronized (r) {
                if (r.flag)
                    try {
                        r.wait(); //为保证交替进行,生成一个新对象之后,下一次则进入等待状态
                    } catch (Exception e) {

                    }
                if (x == 0) {
                    r.name = "mike";
                    r.sex = "man";
                } else {
                    r.name = "丽丽";
                    r.sex = "女";
                }
                r.flag = true;
                r.notify(); // 唤醒处于等待的一个线程,若有多个,则随机唤醒
                x = (x + 1) % 2;
            }


        }
    }

}


class Output implements Runnable {
    private Resourse1 r;

    Output(Resourse1 r) {
        this.r = r;
    }

    public void run() {
        while (true) {
            synchronized (r) {
                if (!r.flag)
                    try {
                        r.wait();
                    } catch (Exception e) {

                    }
                r.flag = false;

                r.notify();

                if ((r.name == "mike" && r.sex == "女") || (r.name == "丽丽" && r.sex == "man")) // 判断是否出现线程不安全现象:人妖
                System.out.println(r.name + "......" + r.sex);
            }

        }

    }
}


public class InputOutputDemo {
    public static void main(String[] args) {
        Resourse1 r = new Resourse1();
        new Thread(new Input(r)).start();
        new Thread(new Output(r)).start();
    }
}

/*
优化InputOutputDemo
*/
package day12;

class Resourse2 {
    String name;
    String sex;
    private int x;
    boolean flag = false; // 默认当前无资源

    public synchronized void set() {
        if (flag)
            try {
                wait(); //为保证交替进行,生成一个新对象之后,下一次则进入等待状态
            } catch (Exception e) {

            }
        if (x == 0) {
            name = "mike";
            sex = "man";
        } else {
            name = "丽丽";
            sex = "女";
        }

        flag = true;
        x = (x + 1) % 2;

        this.notify(); // 唤醒处于等待的一个线程,若有多个,则随机唤醒
    }

    public synchronized void out() {
        if (!flag)
            try {
                wait();
            } catch (Exception e) {

            }
        flag = false;

        this.notify();

        if ((name == "mike" && sex == "女") || (name == "丽丽" && sex == "man")) // 判断是否出现线程不安全现象:人妖
            System.out.println(name + "......" + sex);
    }
}


class Input2 implements Runnable {
    private Resourse2 r;

    Input2(Resourse2 r) {
        this.r = r;
    }

    public void run() {
        while (true) {
            {
                r.set();
            }
        }

    }
}

class Output2 implements Runnable {
    private Resourse2 r;

    Output2(Resourse2 r) {
        this.r = r;
    }

    public void run() {
        while (true) {
            r.out();
        }

    }
}

public class InputOutputOptimize {
    public static void main(String[] args) {
        Resourse2 r = new Resourse2();
        new Thread(new Input2(r)).start();
        new Thread(new Output2(r)).start();
    }
}
/*
需求:生产者生产一个商品,消费者消费一个商品,交替进行

JDK1.5 中提供了多线程升级解决方案。
将同步Synchronized替换成现实Lock操作。
将Object中的wait,notify notifyAll,替换了Condition对象。
该对象可以Lock锁 进行获取。
该示例中,实现了本方只唤醒对方操作。

Lock:替代了Synchronized
	lock
	unlock
	newCondition()

Condition:替代了Object wait notify notifyAll
	await();
	signal();
	signalAll();


*/

package day12;

import java.util.concurrent.locks.*;

class Resourse {

    private String name;
    private int count = 1;
    private boolean flag = false; // 保证生产者和消费者有且仅有一方在操作

    private Lock lock = new ReentrantLock();

    private Condition condition_pro = lock.newCondition();
    private Condition condition_con = lock.newCondition();

    public void set(String name) throws InterruptedException {
        lock.lock();
        try {
            while (flag)
                condition_pro.await(); //唤醒消费者
            this.name = name + "......" + count++;
            System.out.println(Thread.currentThread().getName() + "生产者" + this.name);
            flag = true; //生产完毕,生产者应该等待
            condition_con.signal(); // 给消费者发送信号,通知其进行消费
        } finally {
            lock.unlock(); //释放锁的动作一定要执行
        }
    }

    public void out() throws InterruptedException {
        lock.lock();
        try {
            while (!flag)
                condition_con.await();
            System.out.println(Thread.currentThread().getName() + "消费者............" + this.name);
            flag = false;
            condition_pro.signal();
        } finally {
            lock.unlock();//释放锁的动作一定要执行
        }


    }


}


class Producer implements Runnable {

    private Resourse res;

    Producer(Resourse res) {
        this.res = res;
    }

    public void run() {
        while (true) {
            try {
                res.set("商品");
            } catch (InterruptedException e) {

            }

        }
    }
}

class Consumer implements Runnable {

    private Resourse res;

    Consumer(Resourse res) {
        this.res = res;
    }

    public void run() {
        while (true) {
            try {
                res.out();
            } catch (InterruptedException e) {

            }

        }
    }
}


public class ProducerConsumerDemo {
    public static void main(String[] args) {

        Resourse res = new Resourse();

        Producer p1 = new Producer(res);
        Producer p2 = new Producer(res);
        Consumer c1 = new Consumer(res);
        Consumer c2 = new Consumer(res);

        new Thread(p1).start();
        new Thread(p2).start();
        new Thread(c1).start();
        new Thread(c2).start();


    }
}

/*
join:
当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。

join可以用来临时加入线程执行。


*/

package day12;


class Demo implements Runnable {
    private int size = 1000;

    Demo(int size) {
        this.size = size;
    }

    Demo() {
    }

    public void run() {
        for (int x = 0; x < size; x++) {
            System.out.println(Thread.currentThread().getName() + "......" + x);
//            System.out.println(Thread.currentThread().toString() + "......" + x);
            Thread.yield();  // 暂停当前线程,释放资源,保证多线程能交替运行,不严格交替
        }
    }
}


public class JoinDemo {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(new Demo(1000));
        Thread t2 = new Thread(new Demo());
        t1.start();

//        t1.setPriority(Thread.MIN_PRIORITY); //设置最低权限
//        t2.setPriority(Thread.MAX_PRIORITY); // 设置最高权限

//        t1.join(); // 在主线程中抢夺CPU执行权,当前激活状态的线程只有t1,直到t1全部执行完毕,主线程与t2交替执行

        t2.start();

//        t1.join(); // 在主线程中抢夺CPU执行权,当前激活状态的线程有t1,t2,直到t1全部执行完毕,主线程与t2交替执行

//        for (int x = 0; x < 1000; x++) {
//            System.out.println(Thread.currentThread().getName() + "......" + x);
////            System.out.println(Thread.currentThread().toString() + "......" + x);
//        }

//        t1.join();// 在主线程中抢夺CPU执行权,当前激活状态的线程有t1,t2,main,三者交替执行

        System.out.println("over");


    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章