1. 线程通信
1.1 线程通信介绍
1.2 两条线程通信
package com.itheima.correspondence;
public class CorrespondenceDemo1 {
/*
两条线程通信
*/
public static void main(String[] args) {
Printer1 p = new Printer1();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (Printer1.class) {
while (true) {
try {
p.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (Printer1.class) {
while (true) {
try {
p.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}
class Printer1 {
int flag = 1;
public void print1() throws InterruptedException {
if (flag!=1){
// 等待线程2
Printer1.class.wait();
}
System.out.print("传");
System.out.print("智");
System.out.print("教");
System.out.print("育");
System.out.println();
flag = 2;
// 唤醒线程2
Printer1.class.notify();
}
public void print2() throws InterruptedException {
if (flag != 2) {
// 等待线程1
Printer1.class.wait();
}
System.out.print("黑");
System.out.print("马");
System.out.print("程");
System.out.print("序");
System.out.print("员");
System.out.println();
flag = 1;
// 唤醒线程1
Printer1.class.notify();
}
}
1.3 三条线程通信
对于三条线程通信, 使用notifyAll(), 唤醒所有进程以避免死锁
package com.itheima.correspondence;
public class CorrespondenceDemo2 {
/*
三条线程通信
问题: sleep方法和wait方法的区别?
回答:
sleep方法是线程休眠, 时间到了自动醒来, sleep方法在休眠的时候, 不会释放锁.
wait方法是线程等待, 需要由其它线程进行notify唤醒, wait方法在等待期间, 会释放锁.
*/
public static void main(String[] args) {
Printer2 p = new Printer2();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (Printer2.class) {
while (true) {
try {
p.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (Printer2.class) {
while (true) {
try {
p.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (Printer2.class) {
while (true) {
try {
p.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}
class Printer2 {
int flag = 1;
public void print1() throws InterruptedException {
if (flag != 1) {
Printer2.class.wait();
}
System.out.print("传");
System.out.print("智");
System.out.print("教");
System.out.print("育");
System.out.println();
flag = 2;
Printer2.class.notifyAll();
}
public void print2() throws InterruptedException {
if (flag != 2) {
Printer2.class.wait();
}
System.out.print("黑");
System.out.print("马");
System.out.print("程");
System.out.print("序");
System.out.print("员");
System.out.println();
flag = 3;
Printer2.class.notifyAll();
}
public void print3() throws InterruptedException {
if (flag != 3) {
Printer2.class.wait();
}
System.out.print("传");
System.out.print("智");
System.out.print("大");
System.out.print("学");
System.out.println();
flag = 1;
Printer2.class.notifyAll();
}
}
1.4 三条线程通信的优化
package com.itheima.correspondence;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class CorrespondenceDemo3 {
/*
三条线程通信 - 优化:
将同步信号synchronized换成ReentrantLock
*/
public static void main(String[] args) {
Printer3 p = new Printer3();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
class Printer3 {
ReentrantLock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
int flag = 1;
public void print1() throws InterruptedException {
// 上锁
lock.lock();
if (flag != 1){
// 线程1等待, c1绑定线程1
c1.await();
}
System.out.print("传");
System.out.print("智");
System.out.print("教");
System.out.print("育");
System.out.println();
flag = 2;
c2.signal();
// 解锁
lock.unlock();
}
public void print2() throws InterruptedException {
lock.lock();
if (flag != 2){
// 线程2等待, c2绑定线程2
c2.await();
}
System.out.print("黑");
System.out.print("马");
System.out.print("程");
System.out.print("序");
System.out.print("员");
System.out.println();
flag = 3;
c3.signal();
lock.unlock();
}
public void print3() throws InterruptedException {
lock.lock();
if (flag != 3){
// 线程3等待, c3绑定线程3
c3.await();
}
System.out.print("传");
System.out.print("智");
System.out.print("大");
System.out.print("学");
System.out.println();
flag = 1;
c1.signal();
lock.unlock();
}
}
1.5 案例-生产消费模式
package com.itheima.producer_consumer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class WareHouse {
/**
* 缓冲区域
*/
public static boolean mark = false;
public static ReentrantLock lock = new ReentrantLock();
public static Condition producer = lock.newCondition();
public static Condition consumer = lock.newCondition();
}
package com.itheima.producer_consumer;
public class Producer implements Runnable {
/*
生产者
*/
@Override
public void run() {
while (true) {
WareHouse.lock.lock();
if (WareHouse.mark){
try {
WareHouse.producer.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产者线程生产了包子...");
WareHouse.mark = true;
WareHouse.consumer.signal();
WareHouse.lock.unlock();
}
}
}
package com.itheima.producer_consumer;
public class Consumer implements Runnable{
/*
消费者
*/
@Override
public void run() {
while (true) {
WareHouse.lock.lock();
if (!WareHouse.mark){
try {
WareHouse.consumer.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者吃了包子...");
WareHouse.mark = false;
WareHouse.producer.signal();
WareHouse.lock.unlock();
}
}
}
package com.itheima.producer_consumer;
public class Test {
/*
测试类
*/
public static void main(String[] args) {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}
}
2. 线程生命周期
注: 面试时最好能画出来
3. 线程池
~见Day15最后一节
4. 单例设计
4.1 单例设计-饿汉式
package com.itheima.single_design;
public class SingleDesignDemo1 {
/*
单例设计模式 - 饿汉式(推荐使用, 简单不复杂)
-----------------------------------------------------------------
class Single1 {
private Single1() {
}
public static final Single1 s = new Single1();
}
-----------------------------------------------------------------
*/
public static void main(String[] args) {
Single1 s = Single1.getInstance();
System.out.println(s);
}
}
class Single1 {
private Single1() {
}
private static Single1 s = new Single1();
public static Single1 getInstance() {
return s;
}
}
4.2 单例-懒汉式(延迟加载模式)
package com.itheima.single_design;
public class SingleDesignDemo2 {
/*
单例设计模式 - 懒汉式 (延迟加载模式) --- 面试时可能会问到
--------------------------------------------------
class Single2 {
private Single2() {
}
private static Single2 s;
public static Single2 getInstance() {
if (s == null) {
s = new Single2();
}
return s;
}
}
弊端: 在多线程并发操作的时候, 有可能创建出多个对象.
--------------------------------------------------
class Single2 {
private Single2() {
}
private static Single2 s;
public static Single2 getInstance() {
synchronized (Single2.class) {
if (s == null) {
s = new Single2();
}
}
return s;
}
}
弊端: 效率非常低
--------------------------------------------------
*/
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Single2 s = Single2.getInstance();
System.out.println(s);
}
}).start();
}
}
}
class Single2 {
private Single2() {
}
private static Single2 s;
public static Single2 getInstance() {
// 线程2
// 线程1
// 此处第一个 if (s == null) 用于提高效率, 避免线程多次重复阻塞, 影响效率
if (s == null) {
synchronized (Single2.class) {
// 第二个 if (s == null) 避免产生不同的线程
if (s == null) {
s = new Single2();
}
}
}
return s;
}
}