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

    技术2022-07-10  141

    前言

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

    原视频链接:黑马程序员_毕向东_Java基础视频教程day01:编写HelloWorld程序day02:操作符与条件选择语句day03:循环语句与函数day04:数组day07:继承、抽象类与接口day08:多态day09:异常处理day11:多线程day12:线程安全与同步机制day13:String类day14:集合(ArrayList,LinkedList,HashSet)day15:集合(TreeSet)和泛型)day16:集合(HashMap、TreeMap)day17:集合框架的工具类(Arrays、Collections)day18:IO流(字符流读写)day19:IO流(字节流、转换流读写)day20:IO流(File对象)

    代码

    /* 需求:输入方保存一个人,输出方打印一个人,交替执行 线程间通讯: 其实就是多个线程在操作同一个资源, 但是操作的动作不同。 */ //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"); } }
    Processed: 0.013, SQL: 9