前置可看
Java——多线程和锁_java多线程锁_北岭山脚鼠鼠的博客-CSDN博客
Thread、Runnable、Callable
Lamda表达式_北岭山脚鼠鼠的博客-CSDN博客
如下代码中
好处:
代理对象可以做很多真实对象做不了的事情
真实对象专注做自己的事即可
其中多线程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`类的静态代理模式的工作方式如下:
总之,`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();
}
}
//测试礼让线程
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() +"线程停止执行");
}
}
//观察测试线程的状态
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);//输出状态
}
}
}
多个线程操作同一个资源。
弊端
java的JUC并发包下安全类型的集合
/**
* 测试JUC安全类型的集合
*/
public class TestJUC {
public static void main(String[] args) throws InterruptedException {
CopyOnWriteArrayList list=new CopyOnWriteArrayList();
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保证序列化的.
死锁形成的四个条件: 互斥/请求与保持/不可剥夺条件/循环等待条件。
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();
}
}
}
}
代码实现网上大把.就是两个关键点,一个是消费数量的临界值,第二个就是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());
}
}