【linux应用层

您所在的位置:网站首页 状态机有哪几种 【linux应用层

【linux应用层

2024-07-06 19:41| 来源: 网络整理| 查看: 265

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接: https://blog.csdn.net/xingjing1226/article/details/88973412 什么是线程

线程与进程相似,是一个比进程更小的执行单位。一个进程在其执行过成功可以产生多个线程。同类的多个线程共享同一块内存空间和一组系统资源,多以系统在产生一个县城,或是各个线程之间切换的时候,负担要比进程小很多,正因如此,线程也被称为轻量级进程。

什么是多线程

多线程就是多个线程同时运行或交替运行。单核CPU的话是顺序执行,也就是交替运行。多核CPU的话,每个CPU有自己的运算器,多以在多个CPU中可以同时运行。

线程有什么好处

开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。

为什么提倡多线程而不是多进程

线程就是轻量级进程,是程序执行的最小单位。使用多线程而不是用多进程去进行并发程序的设计,是因为线程间的切换和调度的成本远远小于进程。

同步和异步 形容一次方法调用同步方法调用一旦开始,调用者必须等到方法挑用返回后,才能继续后续行为。异步方法挑用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者可以继续后续的操作。(关于异步目前比较经典以及常用的实现方式就是消息队列:在不使用消息队列服务器的时候,用户的请求数据直接写入数据库,在高并发的情况下数据库压力剧增,使得响应速度变慢。但是在使用消息队列之后,用户的请求数据发送给消息队列之后立即 返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),因此响应速度得到大幅改善。) 并发(Concurrency)和并行(Parallelism) 都可以表示两个或多个任务一起执行,但侧重点不同。并发侧重于多个任务交替执行,多个任务之间有可能串行,多线程在单核CPU的话是顺序执行,也就是交替运行(并发)。并行是真正意义上的同时执行,多线程在多核CPU的话,每个CPU有自己的运算器,所以在多个CPU中可以同事运行(并行)。 高并发

高并发是互联网分布式系统架构设计中必须考虑的因素之一,通常是指通过设计保证系统能同时并行处理很多请求。常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等。

临界区

临界区用来表示一种公共资源(共享数据),可以被多个线程使用。但是每次只能有一个线程使用,一旦临界区资源被占用,其他线程想要使用,必须等待。在并行程序中,临界区资源是保护的对象。

阻塞和非阻塞状态

非阻塞指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回,阻塞则与之相反。

使用线程的几种方式 继承Thread类实现Runnable接口使用线程池(推荐)可以降低资源消耗,提高响应速度和线程的可重用性。 多线程分类 用户线程:运行在前台,执行具体任务。如程序的主线程、连接网络的子线程等都是用户线程。守护线程:运行在后台,为其他前台线程服务,也可以说守护线程就是JVM中非守护线程的“佣人”。一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作。应用在数据库连接池中的检测线程,JVM虚拟机启动后的检测线程。常见的守护线程为垃圾回收线程。通过Thread类的setDaemon(true)方法设置当前线程为守护线程。此方法必须在start()方法前执行,否则会抛出IllegalThreadStateException异常。在守护线程中产生的新线程也是守护线程。不是所有的任务都可以分配给守护线程来执行,如读写操作或者计算逻辑。 线程常用方法 currentThread() 返回对当前正执行的线程对象的引用。getId() 返回当前线程的标识符setName(String name) 设置当前线程名称getName() 返回当前线程的名称setPriority() 设置线程优先级getPriority() 返回当前线程的优先级isAlive() 测试当前线程是否处于活动状态(线程已经启动且尚未终止,处于正在运行或准备运行状态)interrupt() 中断当前线程interrupted() 测试当前线程是否为中断状态,执行后具有将状态标识清除为false的功能isInterrupted() 测试当前线程Thread对象是否为中断状态,但是不知道状态标志isDaemon() 测试当前线程是否为守护线程setDaemon(boolean on) 设置当前线程标记为daemon线程或用户线程start() 用来启动一个线程,当调用start()方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。run() 不需要用户来调用,当通过start()方法启动一个线程后,当线程获得了CPU执行时间,便进入run方法体去执行具体任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。join() 让主线程等子线程运行完之后再继续运行,主线程进入阻塞状态,但不会影响其他正常运行的线程执行,子线程调用join()方法后面的代码,需要等子线程结束主线程才能被唤醒重新获取CPU执行权才能继续执行。在很多情况下,主线程生成并启动子线程,如果子线程需要大量耗时计算,主线程通常会在子线程之前结束,如果主线程要用到子线程处理结果,就要等到子线程完成之后再结束,就需要用到join()方法。源码中wait()的作用是让当前线程等待,而此时的当前线程指的是当前在CPU上运行的线程。子线程加入了主线程,所以虽然调用子线程的wait()方法,但它是通过主线程去调用的,所以休眠的是主线程。sleep(long millis) Thread类的方法,使当前正在执行的线程以执行的毫秒数休眠(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。不释放“锁标志”,给其他线程运行机会,不分优先级,执行后或其他方法join()之后转入阻塞状态,抛出InterruptiedException异常,具有良好的移植性。yield() Thread类的线程让步方法,放弃当前CPU资源,转入就绪(可运行)状态,不释放“锁标志”,放弃时间不确定,可能片刻就会从新获得CPU时间片。只让给自己或者同级线程。检测当前是否有可运行的同级或以上优先级的线程,如果有,就退让CPU使用权,让另外的线程先执行。wait() Object类的方法,运行的线程调用wait()方法,线程会释放掉它占有的“锁标志”,使线程所在对象中的其它synchronized数据可被别的线程使用,JVM会把该线程放入等待池中。wait(long timeout) 在调用notify()、notifyAll()或者指定时间之前,此线程都处于等待状态。notify() Object类的方法,唤醒随机线程。notifyAll() Object类的方法,唤醒所有线程。wait()和notify() 会对对象的“锁标志”操作,所以必须在synchronized函数或者synchronized block中调用。如果在non-synchronized或者non-synchronized blockz中调用,编译不报错,但运行时会发生IllegalMonitorStateException异常。 线程的各种状态 新建状态(New):新创建一个线程对象。就绪状态(Runnable):线程对象创建后,其它线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。阻塞状态(Blocked):阻塞状态是县城因为某种原因放弃了CPU使用权,暂时停止运行,直到线程进入就绪状态,才有机会转到运行状态。阻塞情况一般分为三种等待阻塞:运行的线程执行了wait()方法,JVM会把该线程放入等待池中,直到notify()或者notifyAll(),线程被唤醒后放到锁池(lock blocked pool),释放同步锁使线程回到可运行状态(Runnable)。同步阻塞:运行的线程在获取对象的同步锁(Synchronized)时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。死亡状态(Dead):线程执行完或者因异常退出run()方法,该线程生命周期结束。

java中终止线程的方法

使用退出标志,使线程正常退出,就是当run方法完成后终止使用stop方法强行终止线程(不推荐,因为stop和suspend以及resume一样,都是过期作废的方法,使用它们可能会产生不可预料的结果)。使用interrupt方法中断线程,但是不会终止正在运行的线程,需要加入一个盘福安才可以完成线程的停止。 死锁

死锁问题的产生是由于不同线程分别占用对方需要同步的资源不放,都在等待对方释放资源,从而导致死锁。导致死锁的根源在于不恰当的运用“synchronized”关键字来管理线程对特定对象的访问。

出现死锁必须具备以下几点:

至少两个或两个以上的线程。至少有两个共享资源的锁。至少存在两个线程各自拥有一个锁。两个线程等待获取彼此的锁。

避免死锁的操作:

保证线程访问资源的顺序是一致的。获取锁的时候加超时时间。

释放锁的操作:

同步结束。同步过程中遇见未处理的错误、异常或break等。同步过程中执行了wait()方法,当前线程将会被挂起,释放锁。

不释放锁的操作:

同步过程中调用了sleep()或者yield()。其它线程调用了该现成的suspend()方法。 线程池的五种状态 RUNNING(运行中):线程池的初始化状态。线程池处在RUNNING状态时,能够接受新任务,以及对已添加的任务进行处理。SHUTDOWN(关掉):调用线程池的shutdown()接口时,线程池由RUNNING>>SHUTDOWN。处在SHUTDOWN状态时,不接搜新任务,但是能处理已添加的任务。STOP(停止):调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN)>> STOP。处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。TIDYING(整理):当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由SHUTDOWN >> TIDYING。当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP >> TIDYING。TERMINATED(终止):线程池彻底终止,就变成TERMINATED状态。线程池处在TIDYING状态时,执行完terminated()之后,就会由TIDYING >> TERMINATED。

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3