96SEO 2026-02-19 23:59 47
https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter17/src/com/yinhai

是为完成特定任务、用某种语言编写的一组指令的集合。
简单的说:就是我们写的代码
1进程是指运行中的程序比如我们使用QQ就启动了一个进程操作系统就会为该进程分配内存空间。
当我们使用迅雷又启动了一个进程操作系统将为迅雷分配新的内存空间。
2进程是程序的一次执行过程或是正在运行的一个程序。
是动态过程:有它自身的产生、存在和消亡的过程
3并发:同一个时刻多个任务交替执行造成一种“貌似同时”的错觉简单的说单核cpu实现的多任务就是并发。
4并行:同个时刻多个任务同时执行。
多核cpu可以实现并行。
并发和并行可能都会同时存在
runtime.availableProcessors();System.out.println(cpuNum);}
当主线程结束了可能还有其他的子线程进程可能并没有结束会跑完子线程直到子线程也挂掉了进程就挂掉了
Cat();cat.start();//当main线程启动一个子线程
Thread-0主线程不会阻塞会继续执行//这时我们的主线程和Thread
Thread.currentThread().getName());try
{//往往要重写run方法Thread类实现了Runnable的接口的run方法while
Thread.currentThread().getName());try
补充为什么使用cat.start再由该方法调用run呢而不是使用cat.run呢很好理解因为如果直接调用run方法主线程并不会并列执行该方法而是由主线程main去调用run方法会导致没有实现多线程也就是阻塞下面的语句这种调用不叫多线程
这里的start0是本地方法由JVM调用的而我们重写了该方法的内容所以准确来说是JVM实现了多线程而不是run方法实现多线程
java是单继承的在某些情况下一个类可能已经继承了某个父类这时在用继承Thread类方法创建线程显然不可能了。
java设计者们提供了另外一个方式创建线程就是通过实现Runnable接口来创建线程实际上底层使用了设计模式[代理模式]
Thread(dog);//创建一个Thread对象把实现了dog对象放入Threadthread.start();//
Thread.currentThread().getName());try
可以简单理解为两个类一个ThreadProxy和Tiger都实现了Runnable类在构造器的时候传入tiger到代理对象内此时使用代理对象的start方法就可以动态绑定到我们传入的targer的run方法
ThreadProxy(tiger);threadProxy.start();}
{target.run();//动态绑定运行类型Tiger}}public
{start0();//这个方法时真正实现多线程方法}public
{System.out.println(老虎嗷嗷叫....);}
请编写一个程序创建两个线程一个线程每隔1秒输出hello,world
Thread(t2);thread.start();thread1.start();}
{System.out.println(hello,world
Thread.currentThread().getName());try
Thread.currentThread().getName());try
从java的设计来看通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口
2)实现Runnable接口方式更加适合多个线程共享一个资源的情况并且避免了单继承的限制
继承Thread类创建三个对象去调用strat方法会出现一个很严重的问题多线程冲突都跑去--ticketNum去了会出现来不及减完就会超卖的现象
SellTicket01();sellTicket01.start();sellTicket02.start();sellTicket03.start();}
0){System.out.println(售票结束);break;}try
{e.printStackTrace();}System.out.println(该窗口
Thread.currentThread().getName()
使用Runnable类也会出现上面的情况实际上两个实现的方式本质都一样
{//使用实现Runnable接口方式SellTicket02
Thread(sellTicket002).start();new
Thread(sellTicket002).start();new
Thread(sellTicket002).start();}
0){System.out.println(售票结束);break;}try
{e.printStackTrace();}System.out.println(该窗口
Thread.currentThread().getName()
留下一个问题怎么去解决超卖现象呢看线程同步机制的具体方法内的改善
2.还可以通过使用变量来控制run方法退出的方式停止线程即通知方式。
T();t.start();System.out.println(主线程休眠5秒);//如果希望主线程去控制t1的线程终止就需要修改loop变量//让t1退出run方法从而终止t1线程
{//让主线程休眠10秒再退出Thread线程Thread.sleep(5000);}
{e.printStackTrace();}t.setLoop(false);}
{e.printStackTrace();}System.out.println(T
sleep//在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
interrupt中断线程但并没有真正的结束线程。
所以一般用于中断正在休眠线程
Thread.currentThread().isInterrupted();获取当前是否Interrupted
方法并不会强制终止线程而是提供了一种协作的机制线程可以根据中断状态自行决定是否终止。
所以在下列代码中我们catch了InterruptedException
异常但并没有退出线程的操作导致程序继续执行也就是中断了线程的休眠状态
T();t.setName(yinhai);t.setPriority(Thread.MIN_PRIORITY);//1t.start();//启动子线程//主线程打印5
{Thread.sleep(1000);System.out.println(hi
i);}System.out.println(t.getName()
t.getPriority());//1t.interrupt();//当执行到这里就会中断
{//Thread.currentThread().getName()
获取当前线程的名称System.out.println(Thread.currentThread().getName()
{System.out.println(Thread.currentThread().getName()
休眠中~~~);Thread.sleep(20000);//20秒}
可以加入自己的业务代码//InterruptedException
是捕获到一个中断异常.System.out.println(Thread.currentThread().getName()
yield:线程的礼让。
让出cpu,让其他线程执行但礼让的时间不确定所以也不一定礼让成功。
本意上也是让出cpu给其他线程插队
join:线程的插队。
插队的线程一旦插队成功一定会成功则肯定先执行完插入的线程所有的任务。
次主线程每隔1秒输出hi输出10次.要求:两个线程同时执行当主线程输出5次后就让子线程运行完毕主线程再继续。
{Thread.sleep(1000);System.out.println(主线程(小弟)
Thread.yield();//礼让不一定成功..System.out.println(线程(老大)
{e.printStackTrace();}System.out.println(子线程(老大)
hello...t3.join();//立即将t3子线程插入到main线程让t3先执行}Thread.sleep(1000);//输出一次
让main线程也休眠1s}System.out.println(主线程结束);}
{System.out.println(子线程结束);break;}}}
1.用户线程也叫工作线程以当线程的任务执行完成或通知方式来结束
2.守护线程一般是为工作线程服务的当所有的用户线程结束守护线程自动结束
MyDaemonThread();//如果我们希望当main线程结束后子线程自动结束,只需将子线程设为守护线程即可myDaemonThread.setDaemon(true);//该线程设置为守护线程myDaemonThread.start();for(
{//main线程System.out.println(宝强在辛苦的工作...);Thread.sleep(1000);}}
{Thread.sleep(1000);//休眠1000毫秒}
{e.printStackTrace();}System.out.println(马蓉和宋喆快乐聊天哈哈哈~~~);}}
七个则是Runnable里的可执行的里的细分状态Ready和Running状态取决于调度器选中执行不是start()后就立马执行要取决底层调度器是否执行该线程
T();System.out.println(t.getName()
{System.out.println(t.getName()
t.getState());Thread.sleep(500);}System.out.println(t.getName()
{e.printStackTrace();}}break;}}
1.在多线程编程一些敏感数据不允许被多个线程同时访问此时就使用同步访问技术保证数据在任何时刻最多有一个线程访问以保证数据的完整性。
2.也可以这里理解线程同步即当有一个线程在对内存进行操作时其他线程都不可以对这个内存地址进行操作直到该线程完成操作其他线程才能对该内存地址进行操作。
3)如何理解:就好像某小伙伴上厕所前先把门关上(上锁)完事后再出来(解锁)那么其它小伙伴就可在使用厕所了
Thread(sellTicket002).start();new
Thread(sellTicket002).start();new
Thread(sellTicket002).start();}
sellTick(){//同步方法同一时间只有一个线程来执行sellTick方法if(ticketNum
0){System.out.println(售票结束);return
{e.printStackTrace();}System.out.println(该窗口
Thread.currentThread().getName()
这时候运行状态不一定都会平均分配到到每一个线程上因为是不公平锁三个都在抢这个锁谁抢到就是谁的分析同步原理看下
三个进程去抢这把锁当有一个抢到之后进入run方法输出打印车票然后归还锁到对象上随后加入Blocked进程状态三个一起抢这把锁一直重复执行到结束没抢到的进入Blocked状态抢到的进入Runnable状态执行后退出
1Java在Java语言中引入了对象互斥锁的概念来保证共享数据操作的完整性。
2每个对象都对应于一个可称为互斥锁”的标记这个标记用来保证在任一一时刻只能有一个线程访问该对象。
3关键字synchronized来与对象的互斥锁联系。
当某个对象用synchronized修饰时表明该对象在任一时刻只能由一个线程访问
5同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)
Thread(sellTicket002);thread1.start();thread2.start();thread3.start();}
Object();//6同步方法(静态的)的锁为当前类本身。
//1.
如果在静态方法中要实现一个同步代码块需要像以下方式处理public
{System.out.println(m2);}}//5同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)//同步方法同一时间只有一个线程来执行sellTick方法public
{//2.这时锁在this对象也可以在代码块上写synchronize同步代码块synchronized
{System.out.println(售票结束);return
Thread.currentThread().getName()
1.同步方法如果没有使用static修饰:默认锁对象为this
2.如果方法使用static修饰默认锁对象:当前类.class
ticketNum//这样锁不住无法保证锁的对象是同一个public
多个线程都占用了对方的锁资源但不肯相让导致了死锁在编程是一定要避免死锁的发生.
DeadLockDemo(true);A.setName(A线程);DeadLockDemo
DeadLockDemo(false);B.setName(B线程);A.start();B.start();}
下面就是同步代码System.out.println(Thread.currentThread().getName()
这里获得li对象的监视权System.out.println(Thread.currentThread().getName()
{System.out.println(Thread.currentThread().getName()
这里获得li对象的监视权System.out.println(Thread.currentThread().getName()
有可能出现A线程拿完锁走完了才到B线程也很好的反应了锁的单独拿的性质
3)当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束
4)当前线程在同步代码块、同步方法中执行了线程对象的wait()方法当前线程暂停并释放锁。
1)线程执行同步代码块或同步方法时程序调用Thread.sleep()、
2)线程执行同步代码块时其他线程调用了该线程的suspend()方法将该线程挂起该线程不会释放锁。
提示:应尽量避免使用suspend()和resume()来控制线程这两个方法不再推荐使用
应用程序中事件驱动编程模型允许程序在用户与应用程序界面交互时响应输入事件。
不是常见的做法因为控制台通常不提供直接的键盘事件处理功能也没有
元素来接收键盘输入事件。
控制台应用程序通常是基于命令行的它们等待用户输入然后以文本形式处理用户的命令或数据。
MyListener(printNum)).start();}
true;//通知方式需要定义一个变量接受退出指令public
{System.out.println((int)(Math.random()*100));//随机数Thread.sleep(2000);}
{e.printStackTrace();}}}System.out.println(PrintNum进程退出);}
printNum;//需要定义一个printNum面向对象保证我们改的和运行的是同一个对象Scanner
printNum;//构造器传入Print的对象}Overridepublic
{System.out.println(Q退出等待用户输入...);char
{printNum.setLoop(false);System.out.println(Listener进程退出);break;}else{System.out.println(退出失败
Thread(bank);thread1.start();thread2.start();}
{System.out.println(取完);break;}System.out.println(Thread.currentThread().getName()
如果想要让两个线程近似交替运行取完--bankAccount后休眠不要使用synchronized包起来即可。
锁如果包括休眠的话会等另一个线程休眠完后一起抢。
不包起来就会一个线程开始休眠另一个线程直接抢锁
总结一下执行过快两个thread基本上是同时启动的所以会出现两个争抢的情况如果想两个线程不抢在主线程内加一个sleep即可
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback