现在到了一个很多东西经常用,但其中原理与概念却是模糊的。这也是填鸭式学习的一个后遗症,因此需要用地毯式的搜索来补缺补差。
因此现在也就线程这方面的知识来捋一捋相关的基础概念原理吧。
对于一个知识点的学习毋庸置疑肯定首先需要弄清其概念与工作原理。谈到线程,或许会想到进程,这两者的区别又是什么呢?
什么是进程?
进程就是应用程序的执行实例,有独立的内存空间和系统资源。而任务管理器中的那些运行的应用程序就是很常见的进程了。例如:QQ,浏览器等
特点:(总结其特定可以想成该进程就是电脑中的应用程序)
1.动态创建开启,动态关闭消亡。
2.并发执行,即打开电脑中的QQ时也能运行电脑中的浏览器。
3.各个进程都是独立的,一个QQ的状态并不影响浏览器的状态。
什么是线程?
线程就是进程内部的独立执行单位。真正在CPU上运行的是线程。
例如:用迅雷下载电视剧,此时迅雷就是一个进程,而在其中下的那些电视剧的任务就是线程。
特点:
1.线程是占用进程的资源与空间,而不是特定从计算机中给他分配系统资源与内存空间。
2.同一时间只能有一个线程独立运行,多线程是靠抢占的方式获得执行机会。
3.一个线程可以创建或删除另一个线程。
多线程的优点:
1.很大程度上提高了计算机的系统利用效率
2.充分利用了带宽。
线程分类:
1.系统级线程 2.用户级线程
关于线程的创建与启动
在Java中创建线程有两种方式:(该两种方式都不需要导包)
1.继承java.lang.Thread 类 2.实现java.lang.Runnable接口
1.继承Thread类创建线程
2.实现java.lang.Runnable接口
为什么启动线程是调用start()方法而不是run()方法?
首先需明确线程创建完毕后,启动线程是调用start()方法而不是run()。因为如果调用是run()方法,则只是将MyThread(MyThread2)
作为一个普通类来调用而已,不会创建线程类。而调用 start()方法,则是将MyThread(MyThread2)作为一个线程类创建来调用,
此时通过调用start()方法内部再会调用线程类里面的run()方法。
注:调用了start()方法只能说明该线程处于可运行状态,需要抢占才可执行
这两种创建线程方式的区别(继承Thread类,实现Runnable接口):
1.当使用继承是为了不必要的重新开放,通过继承Thread直接拥有父类中的特征。缺点就是但由于Java是单根继承,因此继承Thread的类由于需求
想再继承其他类就不行了。因此在代码的重塑性会差些
2.当使用实现是面向接口编程,对于代码扩展性要强一些,实现了Runnable接口同时还可以继承其他类。但启动调用的时候比继承方式要麻烦一点
实现方式可以new同一个Thread创建多个线程,且多个线程共享该Runnable资源。
一般情况下我们会使用通过实现Runnable接口来创建多线程
实现Runnable接口相对于继承Thread类来说,有如下的显著优势:
1.适合多个相同代码的线程去处理同一个资源的情况
2.可以避免由于java的单继承特性带来的局限
3.增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的
线程状态:(生命周期)
1.新生状态,即 当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
2.可运行状态,即调用start()方法后变成可以被执行的状态
3.阻塞状态,即由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)
4.死亡状态:即当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
自然终止:正常运行run()方法后终止
异常终止:调用stop()方法让一个线程终止运行
多线程运行机制:是可运行状态下的线程通过抢占资源获取执行机会,因此线程的运行跟系统与硬件配置有关,其结果也会不一样。
线程的调度:多线程处于可运行状态
优先级:反映线程的重要与紧急程度
线程优先级用1—10表示,10的优先级最高,通过优先级默认值为5
更改优先级:setPriorty(int grade)
join() 让调用join的线程加入
sleep(); 让线程阻塞一段时间再运行
注意:main方法本身就是一个线程,一个进程中可以有多个线程,但至少包含一个主线程,main方法就是一个主线程
创建线程是创建主线程之外的线程。