什么是线程?

在讲线程前提一下程序、进程这些基本概念。

程序:是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象

进程:是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程

线程:进程可进一步细化为线程,是一个程序内部的一条执行路径

三者之间的关系:

        程序是一段代码,在计算机运行的是进程,一个进程可以有很过个线程。

 为什么有多线程?

线程 的存在与电脑的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方法启动线程,否则会报线程异常的错误

 

线程中有那些常用的方法?

  1. void start(): 启动线程,并执行对象的run()方法
  2. run(): 线程在被调度时执行的操作
  3. String getName(): 返回线程的名称
  4. void setName(String name):设置该线程名称
  5. static Thread currentThread(): 返回当前线程。在Thread子类中就是this,通常用于主线程和Runnable实
  6. static void yield():线程让步
    暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程
    若队列中没有同优先级的线程,忽略此方法
  7. join() :当某个程序执行流中调用其他线程的 join() 方法时,调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止
    低优先级的线程也可以获得执行
  8. static void sleep(long millis):(指定时间:毫秒)令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队。抛出InterruptedException异常
  9. stop(): 强制线程生命期结束,不推荐使用
  10. boolean isAlive():返回boolean,判断线程是否还活着

                                             线程调度

调度的策略:

  1. 抢占式:高优先级的线程抢占CPU的使用权
  2. 时间片:每个线程平均分配使用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将退出。

形象理解:兔死狗烹,鸟尽弓藏