96SEO 2026-02-23 11:27 20
并行在同一时刻有多个指令在多个CPU上同时执行。

并发在同一时刻有多个指令在单个CPU上交替执行。
独立性进程是一个能独立运行的基本单位同时也是系统分配资源和调度的独立单位
start()使此线程开始执行Java虚拟机会调用run方法()
定义一个类MyThread继承Thread类在MyThread类中重写run()方法创建MyThread类的对象启动线程
Thread{Override//2.重写run方法public
MyThread();t1.setName(线程1);t2.setName(线程2);//4.启动线程t1.start();t2.start();}
target)分配一个新的Thread对象Thread(Runnable
定义一个类MyRunnable实现Runnable接口在MyRunnable类中重写run()方法创建MyRunnable类的对象创建Thread类的对象把MyRunnable对象作为构造方法的参数启动线程
{System.out.println(Thread.currentThread().getName():i);}}
MyRunnable();//创建Thread类的对象把MyRunnable对象作为构造方法的参数//Thread(Runnable
Thread(my,飞机);//启动线程t1.start();t2.start();}
call()计算结果如果无法计算结果则抛出一个异常FutureTask(Callable
定义一个类MyCallable实现Callable接口在MyCallable类中重写call()方法是有返回值的表示多线程的运行结果创建MyCallable类的对象表示多线程要执行的任务创建Future的实现类FutureTask对象把MyCallable对象作为构造方法的参数作用是管理多线程运行的结果创建Thread类的对象把FutureTask对象作为构造方法的参数启动线程再调用get方法就可以获取线程结束之后的结果。
{//创建MyCallable的对象表示多线程要执行的任务MyCallable
MyCallable();//创建FutureTask的对象作用管理多线程运行的结果FutureTaskInteger
Thread(ft);//启动线程t1.start();//获取多线程运行的结果Integer
ft.get();System.out.println(result);}
currentThread()返回对当前正在执行的线程对象的引用
格式Thread-XX序号从0开始的如果我们要给线程设置名字可以用set方法进行设置也可以构造方法设置
当JVM虚拟机启动之后会自动的启动多条线程其中有一条线程就叫做main线程他的作用就是去调用main方法并执行里面的代码在以前我们写的所有的代码其实都是运行在main线程当中
{System.out.println(getName():i);}}
namemy1.setName(高铁);my2.setName(飞机);//Thread(String
MyThread(飞机);my1.start();my2.start();//static
返回对当前正在执行的线程对象的引用System.out.println(Thread.currentThread().getName());//main}
哪条线程执行到这个方法那么哪条线程就会在这里停留对应的时间方法的参数就表示睡眠的时间单位毫秒
1000毫秒当时间到了之后线程会自动的醒来继续执行下面的其他代码
{//每打印一次要休眠一秒Thread.sleep(1000);}
{e.printStackTrace();}System.out.println(getName()
(坦克);//2.开启线程t1.start();t2.start();}
CPU如果线程的优先级相同那么会随机选择一个优先级高的线程获取的
在某一个时刻只能执行一条指令线程只有得到CPU时间片也就是使用权才可以执行指令。
所以说多线程程序的执行是有随机性因为谁抢到CPU的使用权是不一定的
newPriority)更改此线程的优先级线程默认优先级是5线程优先级的范围是1-10数值越大优先级越大抢占cpu的概率越大
{System.out.println(Thread.currentThread().getName()
Thread(ft);t1.setName(飞机);t1.setPriority(10);//System.out.println(t1.getPriority());//5t1.start();MyCallable
Thread(ft2);t2.setName(坦克);t2.setPriority(1);//System.out.println(t2.getPriority());//5t2.start();}
on)将此线程标记为守护线程当运行的线程都是守护线程时Java虚拟机将退出
MyThread2();t1.setName(女神);t2.setName(备胎);//把第二个线程设置为守护线程//当普通线程执行完之后,那么守护线程也没有继续运行下去的必要了.t2.setDaemon(true);t1.start();t2.start();}
i);//表示出让当前CPU的执行权Thread.yield();}}
MyThread();t1.setName(飞机);t2.setName(坦克);t1.start();t2.start();}
MyThread();t.setName(土豆);t.start();//表示把t这个线程插入到当前线程之前。
//t:土豆//当前线程:
main线程t.join();//执行在main线程当中的for
调用start()之后变成就绪状态抢到cpu执行权才能到运行状态当run()里面的程序执行完毕就进入死亡状态
当遇到sleep()或者其他阻塞方法会进入阻塞状态阻塞状态结束之后会变成就绪状态
某电影院目前正在上映国产大片共有100张票而它有3个窗口卖票请设计一个程序模拟该电影院卖票
{e.printStackTrace();}ticket;System.out.println(getName()
MyThread();//起名字t1.setName(窗口1);t2.setName(窗口2);t3.setName(窗口3);//开启线程t1.start();t2.start();t3.start();}
线程执行的随机性导致的,可能在卖票过程中丢失cpu的执行权,导致出现问题
把多条语句操作共享数据的代码给锁起来让任意时刻只能有一个线程执行即可Java提供了同步代码块的方式来解决
}synchronized(任意对象)就相当于给代码加锁了任意对象就可以看成是一把锁
好处解决了多线程的数据安全问题弊端当线程很多时因为每个线程都会去判断同步上的锁这是很耗费资源的无形中会降低程序的运行效率
{//锁对象一定是唯一的,Mythread.class是唯一的字节码文件对象synchronized
{e.printStackTrace();}ticket;System.out.println(getName()
MyThread();//起名字t1.setName(窗口1);t2.setName(窗口2);t3.setName(窗口3);//开启线程t1.start();t2.start();t3.start();}
同步代码块就是把一段代码给锁起来解决多线程操作共享数据带来的安全问题
如果想要把一个方法里面的代码全都锁起来可以直接把synchronized加在方法上
同步静态方法就是把synchronized关键字加到静态方法上
{e.printStackTrace();}ticket;System.out.println(Thread.currentThread().getName()
Thread(mr);t1.setName(窗口1);t2.setName(窗口2);t3.setName(窗口3);t1.start();t2.start();t3.start();}
虽然我们可以理解同步代码块和同步方法的锁对象问题但是我们并没有直接看到在哪里加上了锁在哪里释放了锁为了更清晰的表达如何加锁和释放锁JDK5以后提供了一个新的锁对象Lock
Lock是接口不能直接实例化这里采用它的实现类ReentrantLock来实例化
方法名说明ReentrantLock()创建一个ReentrantLock的实例
{Thread.sleep(100);ticket--;System.out.println(Thread.currentThread().getName()
Thread(ticket);t1.setName(窗口一);t2.setName(窗口二);t3.setName(窗口三);t1.start();t2.start();t3.start();}
线程死锁是指由于两个或者多个线程互相持有对方所需要的资源导致这些线程处于等待状态无法前往执行
{System.out.println(线程A拿到了A锁准备拿B锁);//Asynchronized
{System.out.println(线程A拿到了B锁顺利执行完一轮);}}}
{System.out.println(线程B拿到了B锁准备拿A锁);//Bsynchronized
{System.out.println(线程B拿到了A锁顺利执行完一轮);}}}}}}
MyThread();t1.setName(线程A);t2.setName(线程B);t1.start();t2.start();}
为了解耦生产者和消费者的关系通常会采用共享的数据区域就像是一个仓库
生产者生产数据之后直接放置在共享数据区中并不需要关心消费者的行为
foodFlag0;//是程序是否到达末尾的标志吃货只能吃十碗吃到第十碗就结束public
(Desk.lock){//都末尾if(Desk.count0){break;//没到末尾执行核心代码}else
{//先写让消费者等待的情况//如果桌上没有面条那么消费者就要等if(Desk.foodFlag0){try
{//消费者不需要等待那就是桌子上有面条可以吃吃完之后唤醒生产者继续做面条Desk.count--;System.out.println(吃货正在吃还能再吃Desk.count碗);Desk.foodFlag0;Desk.lock.notifyAll();}}}}}
(Desk.lock){if(Desk.count0){break;}else
{System.out.println(厨师正在做一碗面条);Desk.foodFlag1;Desk.lock.notifyAll();}}}}}
Cook();c.setName(厨师);f.setName(吃货);f.start();c.start();}
阻塞队列继承结构
常见BlockingQueue:ArrayBlockingQueue:
BlockingQueue的核心方法:**put(anObject):
存储元素arrayBlockingQueue.put(汉堡包);//
取元素System.out.println(arrayBlockingQueue.take());System.out.println(arrayBlockingQueue.take());
取不到会阻塞System.out.println(程序结束了);}}2.6.2
java.util.concurrent.ArrayBlockingQueue;public
Thread{ArrayBlockingQueueString
Foodie(ArrayBlockingQueueString
queue.take();System.out.println(food);}
java.util.concurrent.ArrayBlockingQueue;public
Thread{ArrayBlockingQueueString
{while(true){//不断的把面条放到阻塞队列当中try
{queue.put(面条);System.out.println(厨师放了一碗面条);}
java.util.concurrent.ArrayBlockingQueue;public
*///1.创建阻塞队列的对象ArrayBlockingQueueString
ArrayBlockingQueue(1);//2.创建线程的对象并把阻塞队列传递过去Cook
Foodie(queue);//3.开启线程c.start();f.start();}
状态被定义在了java.lang.Thread.State枚举类中State枚举类的源码如下
jdk.internal.misc.VM.toThreadState(threadStatus);}}通过源码我们可以看到Java中的线程存在6种状态每种线程状态的含义如下
线程状态具体含义NEW一个尚未启动的线程的状态。
也称之为初始状态、开始状态。
线程刚被创建但是并未启动。
还没调用start方法。
MyThread
MyThread()只有线程象没有线程特征。
RUNNABLE当我们调用线程对象的start方法那么此时线程对象进入了RUNNABLE状态。
那么此时才是真正的在JVM进程中创建了一个线程线程一经启动并不是立即得到执行线程的运行与否要听令与CPU的调度那么我们把这个中间状态称之为可执行状态(RUNNABLE)也就是说它具备执行的资格但是并没有真正的执行起来而是在等待CPU的度。
BLOCKED当一个线程试图获取一个对象锁而该对象锁被其他的线程持有则该线程进入Blocked状态当该线程持有锁时该线程将变成Runnable状态。
WAITING一个正在等待的线程的状态。
也称之为等待状态。
造成线程等待的原因有两种分别是调用Object.wait()、join()方法。
处于等待状态的线程正在等待其他线程去执行一个特定的操作。
例如因为wait()而等待的线程正在等待另一个线程去调用notify()或notifyAll()一个因为join()而等待的线程正在等待另一个线程结束。
TIMED_WAITING一个在限定时间内等待的线程的状态。
也称之为限时等待状态。
造成线程限时等待状态的原因有三种分别是Thread.sleep(long)Object.wait(long)、join(long)。
TERMINATED一个完全运行完成的线程的状态。
也称之为终止状态、结束状态
提到池大家应该能想到的就是水池。
水池就是一个容器在该容器中存储了很多的水。
那么什么是线程池呢线程池也是可以看做成一个池子在该池子中存储很多个线程。
系统创建一个线程的成本是比较高的因为它涉及到与操作系统交互当程序中需要创建大量生存期很短暂的线程时频繁的创建和销毁线程对系统的资源消耗有可能大于业务处理是对系
统资源的消耗这样就有点舍本逐末了。
针对这一种情况为了提高性能我们就可以采用线程池。
线程池在启动的时会创建大量空闲线程当我们向线程池提交任务的时线程池就
会启动一个线程来执行该任务。
等待任务执行完毕以后线程并不会死亡而是再次返回到线程池中称为空闲状态。
等待下一次任务的执行。
提交任务时池子会创建新的线程对象任务执行完毕线程归还给池子下回再次提交任务时不需要创建新的线程直接复用已有的线程即可
但是如果提交任务时池子中没有空闲线程也无法创建新的线程任务就会排队等待
JDK对线程池也进行了相关的实现在真实企业开发中我们也很少去自定义线程池而是使用JDK中自带的线程池。
newCachedThreadPool()创建一个默认的线程池static
{System.out.println(Thread.currentThread().getName()
创建有上限的线程池*///1.获取线程池对象(创建有上限的线程池)ExecutorService
Executors.newFixedThreadPool(3);//创建无上限的线程池//ExecutorService
Executors.newCachedThreadPool();//2.提交任务pool1.submit(new
MyRunnable());//3.销毁线程池pool1.shutdown();}
ThreadPoolExecutor(核心线程数量,最大线程数量,空闲线程最大存活时间,任务队列,创建线程工厂,任务的拒绝策略);
当我提交5个任务那么有三个任务会被核心线程处理剩下的两个任务会排队等待
当提交8个任务的时候前三个任务会被核心线程处理线程1-3剩下的线程会在队伍里面等待但是三个线程在队伍里面等待已经到达最大长度其他线程不能再等待。
这时候会使用临时线程执行剩下的两个任务线程3和线程4
只有当核心线程都在被占用并且等待队伍也排满的时候才会使用临时线程
不是的如下图任务4-6还在队伍中等待但是任务7-8已经在临时线程中执行
3提交10个任务这个时候任务数量核心线程数量队伍最大长度临时线程数量该怎么办
当核心线程都在工作队伍排满并且临时线程也全都被占用那么剩下的任务会触发任务的拒绝策略
RejectedExecutionHandler是jdk提供的一个任务拒绝策略接口它下面存在4个子类。
任务拒绝策略说明ThreadPoolExecutor.AbortPolicy默认策略丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy丢弃任务但是不抛出异常
这是不推荐的做法。
ThreadPoolExecutor.DiscardOldestPolicy抛弃队列中等待最久的任务
然后把当前任务加入队列中。
ThreadPoolExecutor.CallerRunsPolicy:调用任务的run()方法绕过线程池直接执行。
如果在上面提交10个任务的情况中使用第三种任务拒绝策略DiscardOldestPolicy那么将队伍当中的任务4抛弃并将任务10加入到队列
mythreadpool.a02threadpool2;import
java.util.concurrent.ArrayBlockingQueue;
java.util.concurrent.Executors;
java.util.concurrent.ThreadPoolExecutor;
java.util.concurrent.TimeUnit;public
ThreadPoolExecutor(核心线程数量,最大线程数量,空闲线程最大存活时间,任务队列,创建线程工厂,任务的拒绝策略);参数一核心线程数量
核心线程数量60,//空闲线程最大存活时间TimeUnit.SECONDS,//时间单位(秒)new
ArrayBlockingQueue(3),//任务队列Executors.defaultThreadFactory(),//创建线程工厂new
ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略);}
相当于cpu有4个大脑因为拥有超线程技术将4个大脑虚拟成八个针对四核八线程的电脑的最大并行数是8
cpu密集型运算项目当中计算比较多但是读取文件和读取数据库的操作比较少
作为专业的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