什么是线程?
在讲线程前提一下程序、进程这些基本概念。
程序:是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象
进程:是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程
线程:进程可进一步细化为线程,是一个程序内部的一条执行路径
三者之间的关系:
程序是一段代码,在计算机运行的是进程,一个进程可以有很过个线程。
为什么有多线程?
线程 的存在与电脑的CPU有关,早期CPU是单核的,一个CPU在一个时间单位内只能做一件事。这就存在了问题,当执行的任务比较多的时候单核CPU的处理能力就不够用了。于是后来就有了多核CPU。
CPU核心多了,存在CPU核心之间的通信,他们之间需要协同完成一下任务。
什么是并行和并发?
并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事
并发:一个CPU(采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事
多线程有那些优点?
1. 提高应用程序的响应。对图形化界面更有意义,可增强用户体验。
2. 提高计算机系统CPU的利用率
3. 改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改
什么时候用到多线程?
程序需要同时执行两个或多个任务时!!!
程序需要 实现需要等待的 任务时
需要一些后台运行的程序时
怎么创建一个线程?
从jdk5开始创建一个线程的方法有4种
方式一、继承Thread类重写run方法,通过实例对象的start方法启动线程
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
if (i%2==0) {
System.out.println(i);
}
}
}
}
方式一使用方法:
public class test {
public static void main(String[] args) {
MyThread myThread=new MyThread();
myThread.start();// 不能使用myThread.run()启动线程,应用之间调用不会分出线程处理,这样就变成了单线程了。
}
}
方式二、实现Runnable接口 创建线程,调用则将实现接口的类对象传入Thread
class MyThread implements Runnable{
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
if (i%2==0) {
System.out.println(i);
}
}
}
}
方式二使用方法:
public class test {
public static void main(String[] args) {
MyThread myThread=new MyThread();
Thread t1=new Thread(myThread);
t1.start();
}
}
使用线程过程中需要注意的两个地方
一、 不能直接调用run方法启动线程
二、不能多次使用start方法启动线程,否则会报线程异常的错误
线程中有那些常用的方法?
- void start(): 启动线程,并执行对象的run()方法
- run(): 线程在被调度时执行的操作
- String getName(): 返回线程的名称
- void setName(String name):设置该线程名称
- static Thread currentThread(): 返回当前线程。在Thread子类中就是this,通常用于主线程和Runnable实
- static void yield():线程让步
暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程
若队列中没有同优先级的线程,忽略此方法- join() :当某个程序执行流中调用其他线程的 join() 方法时,调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止
低优先级的线程也可以获得执行- static void sleep(long millis):(指定时间:毫秒)令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队。抛出InterruptedException异常
- stop(): 强制线程生命期结束,不推荐使用
- boolean isAlive():返回boolean,判断线程是否还活着
线程调度
调度的策略:
- 抢占式:高优先级的线程抢占CPU的使用权
- 时间片:每个线程平均分配使用CPU
java中的线程调度
同优先级线程组成先进先出队列(先到先服务),使用时间片策略
高优先级,使用优先调度的抢占式策略
线程的优先级分10个等级
MAX_PRIORITY:10
NORM_PRIORITY:5
MIN _PRIORITY:1
getPriority() :返回线程优先值
setPriority(int newPriority) :改变线程的优先级特点:
线程创建时继承父线程的优先级
低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被执行
补充:线程的分类
Java中的线程分为两类:一种是守护线程,一种是用户线程。
它们在几乎每个方面都是相同的,唯一的区别是判断JVM何时离开。
守护线程是用来服务用户线程的,通过在start()方法前调用thread.setDaemon(true)可以把一个用户线程变成一个守护线程。
Java垃圾回收就是一个典型的守护线程。
若JVM中都是守护线程,当前JVM将退出。
形象理解:兔死狗烹,鸟尽弓藏