前置可看
Java——多线程和锁_java多线程锁_北岭山脚鼠鼠的博客-CSDN博客
线程创建的三种方式
Thread、Runnable、Callable
Thread类
Runable接口
Callable接口
Lamda表达式
Lamda表达式_北岭山脚鼠鼠的博客-CSDN博客
静态代理模式(Thread类的原理)
如下代码中
- 真实对象和代理对象都实现了同一个接口
- 代理对象代理真实角色
好处:
代理对象可以做很多真实对象做不了的事情
真实对象专注做自己的事即可
其中多线程Thread类的底部实现原理就是静态代理模式,不过被代理的实际线程对象是由Thread来创建的。
//静态代理模式
public class StaticProxy {public static void main(String[] args) {you you=new you();//普通调用WeddingCompany weddingCompany=new WeddingCompany(you);weddingCompany.HappyMarry();//lambda表达式调用new WeddingCompany(you).HappyMarry();//多线程new Thread(()-> System.out.println("测试")).start();}
}interface Marry{void HappyMarry();
}//真实角色
class you implements Marry{@Overridepublic void HappyMarry() {System.out.println("鼠鼠结婚了");}
}//代理角色,帮助你结婚
class WeddingCompany implements Marry{//代理的对象-->真实角色private Marry target;public WeddingCompany(Marry target) {this.target = target;}@Overridepublic void HappyMarry() {before();this.target.HappyMarry();after();}private void before() {System.out.println("结婚之前,布置现场");}private void after() {System.out.println("结婚之后,收尾款");}
}
在Java中,`Thread`类底层使用了静态代理模式来实现线程的创建和管理。静态代理模式是一种结构型设计模式,它允许你通过代理对象来控制对真实对象的访问。在`Thread`类中,`Thread`对象作为代理,用于管理真正执行线程任务的工作线程(实际的线程实例)。
具体来说,`Thread`类的静态代理模式的工作方式如下:
- 1. **`Thread`类充当代理:** `Thread`类是代理类,它负责处理线程的生命周期、状态变化等。它提供了方法来启动、暂停、恢复、停止线程等操作。
- 2. **实际线程对象:** 在`Thread`类中,真正执行线程任务的是一个实际的线程对象,这个线程对象通常是继承自`java.lang.Thread`的子类。这个实际的线程对象是被代理的真实对象。
- 3. **调用`start`方法:** 当你调用`Thread`类的`start`方法时,`Thread`对象首先会执行一些必要的准备工作(例如,状态设置等),然后创建一个实际的线程对象,并调用实际线程对象的`run`方法。
- 4. **执行线程任务:** 实际的线程对象执行线程任务。这个任务通常是在子类中的`run`方法中实现的,这是你自己定义的任务逻辑。
- 5. **线程状态管理:** `Thread`类会在合适的时机管理线程的状态变化,例如,当线程启动时,`Thread`对象会将线程状态设置为"RUNNABLE",当线程执行完毕时,`Thread`对象会将线程状态设置为"TERMINATED"。
总之,`Thread`类在底层使用静态代理模式,通过代理对象管理实际线程对象的创建、启动、暂停、停止等操作,以实现对线程的管理和控制。这种方式使得线程的管理更加便捷,同时也遵循了代理模式的思想。
线程状态—五大状态
停止线程
//测试stop
//1.建议线程正常停止--->利用次数,不建议死循环
//2.建议使用标志位--->设置一个标志位
//3.不要使用stop或者destory
public class TestStop implements Runnable{//1.设置一个标志位private boolean flag=true;@Overridepublic void run() {int i=0;while (flag){System.out.println("run...Thread"+i++);}}//2.设置公开方法停止线程public void stop(){this.flag=false;}public static void main(String[] args) throws IOException {TestStop testStop=new TestStop();new Thread(testStop).start();for(int i=0;i<1000;i++){System.out.println("main"+i);if(i==900){//调用stop方法切换标志位,让线程停止testStop.stop();System.out.println("线程停止了");}}System.in.read();}
}
线程休眠_sleep
线程礼让_yeild
//测试礼让线程
public class TestYield {public static void main(String[] args) {MyYield myYield=new MyYield();new Thread(myYield,"a").start();new Thread(myYield,"b").start();}
}class MyYield implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "线程开始执行");Thread.yield();//礼让System.out.println(Thread.currentThread().getName() +"线程停止执行");}
}
线程强制执行_join
线程状态观测
//观察测试线程的状态
public class TestState {public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{for(int i=0;i<5;i++){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println("//");});//观察状态Thread.State state = thread.getState();System.out.println(state); //new//观察启动后thread.start();//启动线程state = thread.getState();System.out.println(state);//runwhile(state!=Thread.State.TERMINATED){//只要线程不终止,就一直输出状态Thread.sleep(100);state=thread.getState();//更新线程状态System.out.println(state);//输出状态}}
}
线程优先级
守护(daemon)线程
线程同步
多个线程操作同一个资源。
同步方法及同步块
弊端
同步块
CopyOnWriteArrayList
java的JUC并发包下安全类型的集合
/*** 测试JUC安全类型的集合*/
public class TestJUC {public static void main(String[] args) throws InterruptedException {CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>();for(int i=0;i<10000;i++){new Thread(()->{list.add(Thread.currentThread().getName());}).start();}Thread.sleep(3000);System.out.println(list.size());}
}
安全问题得到解决
在其实现源码里面可以看见有两个JUC的关键词,volatile保证唯一,transient保证序列化的.
死锁
死锁形成的四个条件: 互斥/请求与保持/不可剥夺条件/循环等待条件。
Lock(锁)
ReentrantLock可重入锁类.
在CopyOnWriteArrayList里面就有这个类
/*** 测试lock锁*/
public class TestLock {public static void main(String[] args) {TestLock2 testLock2=new TestLock2();new Thread(testLock2).start();new Thread(testLock2).start();new Thread(testLock2).start();}
}
class TestLock2 implements Runnable{int tickNums=10;//定义锁private final ReentrantLock lock=new ReentrantLock();@Overridepublic void run() {while(true){try{//此处加锁lock.lock();if(tickNums>0){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(tickNums--);}else{break;}}finally {//解锁lock.unlock();}}}
}
Synchronized和Lock的对比
线程协作和通信
生产者和消费者模式
管程法
代码实现网上大把.就是两个关键点,一个是消费数量的临界值,第二个就是wait 和notify的使用.
信号灯法
上面管程法用的是容器,这里用的是标志位,但是也相当于是容量为1的容器.
线程池
就像是IO的缓冲池,Mybatis的缓存,数据库的连接池,JVM的常量池
public class TestPool {public static void main(String[] args) {//1.创建服务//参数为:线程池大小ExecutorService service= Executors.newFixedThreadPool(10);//执行service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());//2.关闭连接service.shutdown();}
}class MyThread implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
}