- 程序-Process:指令和数据的有序集合,是一个静态的概念
- 进程-Thread:执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位
- 线程:CPU调度和执行的单位,通常一个进程包含多个线程
- 独立的执行路径
- 如果开辟了多个线程,则线程的调度由调度器(cpu)安排调度
- 线程会带来额外的开销,如:cpu调度时间、并发控制开销
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
- 优点:
- 代理对象可以帮助真实对象做其他重复性的工作
- 真实对象只需要专注做自己的工作即可
- 静态代理总结
- 真实对象和代理对象的要实现同一个接口
- 代理对象要代理真实对象
- 实例
public class StaticProxy {
public static void main(String[] args) {
You you = new You();
new WeddingCompany(you).HappyMarry();
//类似多线程
new Thread(()->System.out.println("run...")).start();
}
}
// 定义都要实现的接口
interface Marry{
void HappyMarry();
}
// 真实对象
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("我要结婚了!!!");
}
}
// 代理对象
class WeddingCompany implements Marry{
private Marry target;
WeddingCompany(Marry target){
this.target=target;
}
@Override
public void HappyMarry() {
before();
target.HappyMarry();
after();
}
private void before() {
System.out.println("结婚之前,布置现场");
}
private void after() {
System.out.println("结婚之后,清理现场");
}
}
- 并发:同一个对象被多个线程同时操作
- 线程同步:一种等待机制
- 当多个线程访问同一个对象,并且一些线程还要修改这个对象时,需要线程同步
- 队列+锁
- 由来:由于同一个进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了冲突,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制synchronized,当一个线程获得对象的排他锁,独占资源,其他线程必须等待其释放后才可以使用该对象
- 问题:
- 一个线程持有锁会导致其他所有需要此锁的线程挂起
- 在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题
- 如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题
package syn;
// 使用多线程不安全的买票
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicker buyTicker = new BuyTicker();
new Thread(buyTicker,"老师1").start();
new Thread(buyTicker,"老师2").start();
new Thread(buyTicker,"老师3").start();
new Thread(buyTicker,"老师4").start();
}
}
class BuyTicker implements Runnable{
private int ticketNums = 10;
boolean flag = true;
// synchronized同步方法,锁的是this
private synchronized void buy() throws InterruptedException {
if(ticketNums<=0){
flag=false;
return;
}
Thread.sleep(100);
//买票
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
}
@Override
public void run() {
while(this.flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package syn;
public class UnsafeBank {
public static void main(String[] args) {
Accout accout = new Accout(400,"百度银行卡");
new Drawing(accout,300,"小红").start();
new Drawing(accout,300,"小李").start();
new Drawing(accout,300,"小哥").start();
}
}
// 账户类
class Accout{
int money;
String name;
public Accout(int money,String name){
this.money=money;
this.name = name;
}
}
// 银行模拟取钱
class Drawing extends Thread{
Accout accout;
// 要去的钱
int drawingMoney;
//现在手里面的钱
int nowMoney;
public Drawing(Accout accout,int drawingMoney,String name){
super(name);
this.accout=accout;
this.drawingMoney=drawingMoney;
}
@Override
public void run() {
// 锁的对象就是变化的量
synchronized (accout){
if(accout.money-drawingMoney<0){
System.out.println(this.getName()+"钱不够,取不了");
return;
}
// sleep加大问题发生的可能性
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 卡内余额
accout.money = accout.money-drawingMoney;
nowMoney=nowMoney+drawingMoney;
System.out.println(accout.name+"余额为:"+accout.money);
System.out.println(this.getName()+"手里的钱:"+nowMoney);
}
}
}
// 线程不安全的集合
public class UnsafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
Thread.sleep(100);
System.out.println(list.size());
}
}
- 多个线程各自占有一些共享资源,并且相互等待其他线程占有资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情况
- 某个同步块同时拥有两个以上的对象锁时,就可能发生死锁问题
package syn;
// 死锁:多个线程相互抱着对方需要的资源,然后形成僵持
public class DeadLock {
public static void main(String[] args) {
Makeup m1 = new Makeup(0,"女孩1");
Makeup m2 = new Makeup(1,"女孩2");
m1.start();
m2.start();
}
}
// 口红
class Lipstick{
}
// 镜子
class Mirror{
}
class Makeup extends Thread{
// 需要的资源只有一份,用static保证
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;//选择
String girlName;//使用化妆品的人
public Makeup(int choice,String girlName){
this.choice = choice;
this.girlName = girlName;
}
// 化妆
private void makeup() throws InterruptedException {
if(choice==0){
//获得口红的锁
synchronized (lipstick){
System.out.println(this.girlName+"获得口红");
Thread.sleep(1000);
// synchronized (mirror){
// System.out.println(this.girlName+"获的镜子");
// }
}
synchronized (mirror){
System.out.println(this.girlName+"获的镜子");
}
}else{
//获得镜子的锁
synchronized (mirror){
System.out.println(this.girlName+"获得镜子");
Thread.sleep(2000);
// synchronized (lipstick){
// System.out.println(this.girlName+"获得口红");
// }
}
synchronized (lipstick){
System.out.println(this.girlName+"获得口红");
}
}
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 使用多线程不安全的买票
public class UnsafeBuyTicketUseLock {
public static void main(String[] args) {
BuyTicker1 buyTicker = new BuyTicker1();
new Thread(buyTicker,"老师1").start();
new Thread(buyTicker,"老师2").start();
new Thread(buyTicker,"老师3").start();
new Thread(buyTicker,"老师4").start();
}
}
class BuyTicker1 implements Runnable{
private int ticketNums = 10;
boolean flag = true;
// 定义锁
private final ReentrantLock lock = new ReentrantLock();
// synchronized同步方法,锁的是this
private void buy() throws InterruptedException {
try{
lock.lock();
if(ticketNums<=0){
flag=false;
return;
}
Thread.sleep(100);
//买票
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
}finally {
lock.unlock();
}
}
@Override
public void run() {
while(this.flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}