7 多线程

7.1 进程和线程

1、进程

  • 进程是一个正在执行中的程序

  • 每一个进程都有一个执行顺序,该顺序是一个执行路径,或者叫做一个控制单元

2、线程

  • 线程就是进程中的一个独立控制单元

  • 线程在控制着进程的执行

  • 一个进程中至少有一线程


7.2 创建线程的方式

第一种:继承Thread类

步骤:

定义类继承Thread

复写Thread类中的run方法

调用线程的start方法,该方法的作用:启动线程,并调用run方法。

class Demo extends Thread{

    public void run(){

        System.out.println("demo run");

    } 

}

class ThreadDemo{

    public static void main(String[] args){

        Demo d = new Demo();//创建线程

        d.start();

    }

}


多线程的特点:随机性

多线程运行时,每一次运行的结果都不同。每个线程都在争夺CPU的执行权,谁得到谁就运行。在某一时刻,只能有一个程序运行(多核除外)。CPU在做着快速的切换,以达到同时运行的效果。


run方法用于存储线程要运行的代码

static Thread currentThread():获取当前线程对象

getName():获取线程名称

setName或者构造函数:设置线程名称


第二种:实现Runnable接口

步骤:

定义类实现Runnable接口

覆盖Runnable接口中的run方法

通过Thread类建立线程对象

将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数

调用Thread类的start方法开启线程,并调用Runnable接口子类额run方法


实现方式和继承方式的区别

  • 继承Thread:线程代码存放在Thread子类run方法中

  • 实现Runnable:线程代码存放在接口的子类额run方法中

  • 实现方法的好处:避免了单继承额局限性,在定义线程时,建议使用实现方式


class PrimeRun implements Runnable{

  public void run(){

    System.out.println("demo run");


}

class ThreadDemo{

    public static void main(String[] args){

       PrimeRun p = new PrimeRun();//创建线程

       new Thread(p).start();

}

}



7.3 同步

1、同步的前提

  • 必须要有两个或者两个以上的线程

  • 必须是多个线程使用同一个锁

  • 必须保证同步中只有一个线程在运行


2、同步的好处和弊端

好处:解决了多线程额安全问题

弊端:多个线程都需要判断锁,比较消耗资源。


3、同步代码块

synchronized(对象){

    需要被同步的代码

}

对象如同锁,持有锁的线程可以在同步中执行。没有持有锁的线程即使获取了CPU的执行权也进不去,因为没有获取锁。


4、同步函数

将synchronized作为函数的修饰符

public synchronized void add(){}

同步函数用的锁:

函数需要被对象调用,那么函数都有一个所属对象引用,就是this,所以同步函数使用的锁是this。

如果同步函数被静态修饰后,使用的锁是Class对象,类名.class。


死锁:同步嵌套


5、新特性:

jdk1.5之后提供了多线程升级解决方案

  • 将Synchronized替换成实现Lock操作,加锁:lock(),解锁:unlock()

  • 将Object中的wait、notify、notifyall替换成了Condition对象,该对象可通过Lock获取。等待:await(0,唤醒:signal()。


7.4 停止线程

stop方法已经过时。

只有一种方法停止线程:run方法结束。一般都将代码放在循环体中,所以只需要加个标记,控制循环,就可以让run方法结束。

特殊情况:

当线程处于等待状态,就读取不到标记,那么就不会结束。这是就需要使用Interrupt()方法,让等待状态 线程回到活动状态。


7.5 Join和yield

1、Join方法

  • 临时加入线程

  • 加入线程时,当前线程会进入等待状态,直到加入的线程运行完毕,再回到活动状态。

2、yield方法

    暂停当前正在执行的线程,并执行其他线程。


7.6 优先级

优先级有1到10,所有线程默认都是5。通常只取1、5和10,为了便于阅读将这三个设为了常量,分别对应MIN_PRIORITY、NORM_PRIORITY、MAX_PRIORITY