前置可看
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{
@Override
public void HappyMarry() {
System.out.println("鼠鼠结婚了");
}
}
//代理角色,帮助你结婚
class WeddingCompany implements Marry{
//代理的对象-->真实角色
private Marry target;
public WeddingCompany(Marry target) {
this.target = target;
}
@Override
public 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;
@Override
public 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{
@Override
public 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);//run
while(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();
@Override
public 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{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}