多线程--基础概念

来源:互联网 发布:sql server下载版安装 编辑:程序博客网 时间:2024/06/07 17:27
最近时间多,准备对多线程的一些知识进行温故,让自己有进一步的提升

多线程编程的一些基础概念

什么是进程和线程?两者的区别是什么?

1.进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。(进程是资源分配的最小单位),比如window任务窗口中的.exe运行程序。
2.线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
进程与线程的区别:
a.多个线程的内部数据和状态都是完全独立的,而多线程是共享一块内存空间和一组系统资源,有可能相互影响。
b.线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要小。
c.一个进程可以包含一个线程或者多个线程
d.一个程序实现多个代码同时交替运行就需要产生多个线程

多线程编程的目的?

最大限度地利用CPU资源,当某一个线程的处理不需要占用CPU而只和I/O等资源进行打交道时。让需要占用CPU资源的其他线程有机会获得CPU资源,从根本上来说,这就是多线程编程的最终目的。

Java多线程实现的方式:

1.继承Thread类,Thread类也实现了Runnable接口,因此实现了Runable接口中的run方法;
2.实现Runabble接口
将我们要执行的代码放入到run方法中,然后通过start()方法来启动线程,start方法首先会为线程的执行准备好系统资源,然后再去调用run方法。当 某个类继承了Thread类之后,该类就叫做了一个线程类。

查看源代码可以知道,当使用第一种方式来生成线程对象时,我们需要重写run方法,因为Thread类的run方法此时什么事情也不做,所以需要我们重写
当使用第二种方式生成线程对象时,我们需要实现Runable接口中的run方法。然后使用new Thread(new MyThread()) MyThread实现了Runable来生成线程对象。这时的线程对象的run方法或调用MyThread类的run方法。这样我们编写的run方法就执行了。

多线程的状态:

这里写图片描述
线程在一定条件下。状态会发生变化。
线程变化的状态转换图例如以下:
  1、新建状态(New):新创建了一个线程对象。
  2、可运行状态(Runnable):线程对象创建后,其它线程调用了该对象的start()方法,将分配资源。
该状态的线程位于可执行线程池中,变得可执行,等待获取CPU的使用权。
  3、执行状态(Running):就绪状态的线程获取了CPU。执行程序代码。
  4、堵塞状态(Blocked):堵塞状态是线程由于某种原因放弃CPU使用权。临时停止执行。直到线程进入就绪状态,才有机会转到执行状态。
堵塞的情况分三种:
  (一)、等待堵塞:执行的线程执行wait()方法,JVM会把该线程放入等待池中。
  (二)、同步堵塞:执行的线程在获取对象的同步锁时,若该同步锁被别的线程占用。则JVM会把该线程放入锁池中。
  (三)、其它堵塞:执行的线程执行sleep()或join()方法,或者发出了I/O请求时。JVM会把该线程置为堵塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完成时。线程又一次转入就绪状态。
  5、死亡状态(Dead):线程运行完了或者因异常退出了run()方法,该线程结束生命周期。

详细说明:1、线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口,但无论如何,当我们new了这个对象后。线程就进入了初始状态;2、当该对象调用了start()方法,就进入可执行状态;3、进入可执行状态后,当该对象被操作系统选中。获得CPU时间片就会进入执行状态;4、进入执行状态后情况就比较复杂了    4.1run()方法或main()方法结束后,线程就进入终止状态;    4.2、当线程调用了自身的sleep()方法或其它线程的join()方法,就会进入堵塞状态(该状态既停止当前线程,但并不释放所占有的资源)。当sleep()结束或join()结束后。该线程进入可执行状态,继续等待OS分配时间片;    4.3、线程调用了yield()方法,意思是放弃当前获得的CPU时间片,回到可执行状态,这时与其它进程处于同等竞争状态,OS有可能会接着又让这个进程进入执行状态。   4.4、当线程刚进入可执行状态(注意,还没执行),发现将要调用的资源被synchroniza(同步),获取不到锁标记。将会马上进入锁池状态,等待获取锁标记(这时的锁池里或许已经有了其它线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获得锁标记后,就转入可执行状态。等待OS分配CPU时间片。   4.5、当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的全部资源,与堵塞状态不同)。进入这个状态后。是不能自己主动唤醒的,必须依靠其它线程调用notify()notifyAll()方法才干被唤醒(因为notify()仅仅是唤醒一个线程,但我们由不能确定详细唤醒的是哪一个线程。或许我们须要唤醒的线程不可以被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后会进入锁池。等待获取锁标记。

线程的优先级

1.线程的优先级是一个1-10的数字,线程总是存在优先级,优先级范围在1~10之间,优先级的设置通过setPriority(8)进行设置,线程默认的优先级为5。
2.设计程序的时候千万不能依赖线程的优先级,因为线程调度的优先级是没有保证的。只能把线程的优先级当做一种程序优化的手段而已。
3.线程的优先级用1-10之间的整数表示,数值越大优先级越高。