前言
本期任务:毕向东老师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");
}
}