前言
本期任務:畢向東老師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");
}
}