java线程一(基础)
来源:互联网 发布:淘宝家装日记极有家 编辑:程序博客网 时间:2024/06/06 04:45
一.Java中关于应用程序和进程相关的概念
在Java中,一个应用程序对应着一个JVM实例(也有地方称为JVM进程),一般来说名字默认为java.exe或者javaw.exe(windows下可以通过任务管理器查看)。Java采用的是单线程编程模型,即在我们自己的程序中如果没有主动创建线程的话,只会创建一个线程,通常称为主线程。但是要注意,虽然只有一个线程来执行任务,不代表JVM中只有一个线程,JVM实例在创建的时候,同时会创建很多其他的线程(比如垃圾收集器线程)。
由于Java采用的是单线程编程模型,因此在进行UI编程时要注意将耗时的操作放在子线程中进行,以避免阻塞主线程(在UI编程时,主线程即UI线程,用来处理用户的交互事件)。
二.Java中如何创建线程
在java中如果要创建线程的话,一般有两种方式:1)继承Thread类;2)实现Runnable接口。
*一个线程的启动必须要用start()来启动,run()方法由JVM来调用。如果自己调用run()的话,只是一个单纯的方法调用。
需要特别注意的是:不能对同一线程对象两次调用start()方法。
*还有第三中方式,使用ExecutorService、Callable、Future实现有返回结果的多线程,将在并发包里再讲。
1.继承Thread类
继承Thread类的话,必须重写run方法,在run方法中定义需要执行的任务。
class
MyThread
extends
Thread{
private
static
int
num =
0
;
public
MyThread(){
num++;
}
@Override
public
void
run() {
System.out.println(
"主动创建的第"
+num+
"个线程"
);
}
}
2.实现Runnable接口
在Java中创建线程除了继承Thread类之外,还可以通过实现Runnable接口来实现类似的功能。实现Runnable接口必须重写其run方法。
下面是一个例子:
public
class
Test {
public
static
void
main(String[] args) {
System.out.println(
"主线程ID:"
+Thread.currentThread().getId());
MyRunnable runnable =
new
MyRunnable();
Thread thread =
new
Thread(runnable);
thread.start();
}
}
class
MyRunnable
implements
Runnable{
public
MyRunnable() {
}
@Override
public
void
run() {
System.out.println(
"子线程ID:"
+Thread.currentThread().getId());
}
}
三.线程的状态
在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解。
线程从创建到最终的消亡,要经历若干个状态。一般来说,线程包括以下这几个状态:
- 创建(new)状态: 准备好了一个多线程的对象(new Thread())。
- 就绪(runnable)状态: 调用了
start()
方法, 等待CPU进行调度 (因为线程的运行需要一些条件(比如内存资源,在JVM内存区域划分中程序计数器、Java栈、本地方法栈都是线程私有的,所以需要为线程分配一定的内存空间),只有线程运行需要的所有条件满足了,才进入就绪状态。) - 运行(running)状态: 执行
run()
方法 - 阻塞(blocked)状态: 处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
- 终止(dead)状态: 线程销毁(当由于突然中断或者子任务执行完毕,线程就会被消亡)
下面这副图描述了线程从创建到消亡之间的状态:
四.上下文切换
对于单核CPU来说(对于多核CPU,此处就理解为一个核),CPU在一个时刻只能运行一个线程,当在运行一个线程的过程中转去运行另外一个线程,这个叫做线程上下文切换(对于进程也是类似)。
由于可能当前线程的任务并没有执行完毕,所以在切换时需要保存线程的运行状态,以便下次重新切换回来时能够继续切换之前的状态运行。举个简单的例子:比如一个线程A正在读取一个文件的内容,正读到文件的一半,此时需要暂停线程A,转去执行线程B,当再次切换回来执行线程A的时候,我们不希望线程A又从文件的开头来读取。
因此需要记录线程A的运行状态,那么会记录哪些数据呢?因为下次恢复时需要知道在这之前当前线程已经执行到哪条指令了,所以需要记录程序计数器的值,另外比如说线程正在进行某个计算的时候被挂起了,那么下次继续执行的时候需要知道之前挂起时变量的值时多少,因此需要记录CPU寄存器的状态。所以一般来说,线程上下文切换过程中会记录程序计数器、CPU寄存器状态等数据。
说简单点的:对于线程的上下文切换实际上就是 存储和恢复CPU状态的过程,它使得线程执行能够从中断点恢复执行。
虽然多线程可以使得任务执行的效率得到提升,但是由于在线程切换时同样会带来一定的开销代价,并且多个线程会导致系统资源占用的增加,所以在进行多线程编程时要注意这些因素。
- java线程一(基础)
- java线程---基础(一)
- java线程编程(一):线程基础
- JAVA线程基础(一)
- java基础---线程一
- Java线程基础一
- Java并发总结(一):线程基础
- Java基础笔记之多线程(一)
- Java学习:线程基础(一)
- Java并发总结(一):线程基础
- Java基础——线程(一)
- java多线程(一)之多线程基础
- 线程篇(一):Java中的线程(基础)
- java基础之多线程(一)
- 线程基础(一)
- 线程基础(一)
- java线程池(一) -- 线程基础
- Java并发基础(一)-线程基础
- HDU 2669 Romantic(乘法逆元)
- linux mysql的二进制日志(bin-log)
- Java class文件信息
- 在Ubuntu16.04下安装jdk-8u111-linux-x64.tar.gz并配置Java环境
- python过滤html文档中的Tag标签
- java线程一(基础)
- Python3之优化版粘包解决问题
- 快速实现酷炫的ViewPager卡片效果
- ZYNQ中的UIO驱动和中断程序学习【Xilinx-Petalinux学习】
- GPU编程自学10 —— 流并行
- Intel® Media Server Studio安装
- 母函数的用法
- Android 编辑个人资料,图片可拖拽排序
- kNN算法理论