一、什么是线程?

1、进程的概念

  • 进程是指可执行程序并存放在计算机存储器的一个指令序列,它是一个动态执行的过程。
  • 有的软件只有一个进程,如记事本;有的软件是由多个进程组成的。
  • 早期的进程是单任务的,只能运行一个程序,现在的操作系统是多任务的操作系统,多个程序可以同时运行。

    2、什么是线程?

  • 线程是比进程还要小的运行单位,一个进程包含多个线程。

  • 比如一个程序是由很多行代码组成的,这些代码就可以分成很多块,放到线程中,分别执行。
  • 线程相当于一个子程序

    时间片的轮转:把CPU的执行时间分成很多的小块,每一小块的时间都是固定的,我们将这一小块的时间成为时间片;时间片的时间可以非常短,比如1ms,多个软件同时运行,多个软件分别获取时间片去处理,对于CPU来讲,这些软件都是轮流运行的,但是由于分别运行的时间间隔非常短,对于我们使用者而言是察觉不到的,可以认为这些软件是同时运行的。

二、线程的创建

1、创建线程的几种方式

  • 创建一个Thread类,或者一个Thread子类的对象。
  • 创建一个Runnable接口的类的对象 。

    2、Thread类

  • Thread类是一个线程类,位于java.lang包下 | 构造方法 | 说明 | | —- | —- | | Thread() | 创建一个线程对象 | | Thread(String name) | 创建一个具有指定名称的线程对象 | | Thread(Runnable target) | 创建一个基于Runnable接口实现类的线程对象 | | Thread(Runnable target,String name) | 创建一个基于Runnable接口实现类,并且具有指定名称的线程对象 |

  • Thread类的常用方法 | 方法 | 说明 | | —- | —- | | public void run() | 线程相关的代码写在该方法中(线程体的代码),一般需要重写 | | public void start() | 启动线程的方法 | | public static void sleep(long m) | 线程休眠m毫秒的方法 | | public void join() | 优先执行调用join()方法的线程,抢占资源 |

  • 通过继承Thread类创建线程 ```java class MyThread extends Thread { public MyThread(String name) {

    1. super(name);

    } @Override public void run() {

    1. for (int i = 0; i < 10; i++) {
    2. System.out.println(getName()+"正在运行"+i);
    3. }

    } }

public class ThreadTest { public static void main(String[] args) { MyThread mt1 = new MyThread(“线程1”); MyThread mt2 = new MyThread(“线程2”); mt1.start(); mt2.start();

  1. }

}

  1. <a name="DJpsv"></a>
  2. #### 3、Runnable接口
  3. - 只有一个方法`run()`
  4. - Runnable是Java中用以实现线程的接口
  5. - 任何实现线程功能的类都必须实现该接口,Thread类实际上是实现了Runnable接口的。
  6. - 通过实现Runnable接口的方式创建,(为什么要实现Runnable接口?1、Java不支持多线程;2、不打算重写Thread类的其他方法)
  7. ```java
  8. class PrintRunnable implements Runnable {
  9. @Override
  10. public void run() {
  11. for (int i = 0; i < 10; i++) {
  12. System.out.println(Thread.currentThread().getName()+"正在运行"+i);
  13. }
  14. }
  15. }
  16. public class RunnableTest {
  17. public static void main(String[] args) {
  18. PrintRunnable printRunnable = new PrintRunnable();
  19. Thread thread1 = new Thread(printRunnable,"线程1");
  20. Thread thread3 = new Thread(() -> {
  21. for (int i = 0; i < 10; i++) {
  22. System.out.println(Thread.currentThread().getName() + "正在运行" + i);
  23. }
  24. }, "线程3");
  25. Thread thread2 = new Thread(printRunnable,"线程2");
  26. thread1.start();
  27. thread2.start();
  28. thread3.start();
  29. }
  30. }

三、线程的状态和生命周期

1、线程的状态

  • 新建(new) :当创建一个Thread类或Thread子类对象的时候
  • 可运行(Runnable):当已经创建好的线程对象去调用 start() f方法,这时候就进入了可运行状态,线程什么时候运行是由CPU来决定的,只有当线程获取到CPU的使用权的时候,它才能执行,所以线程调用 start() 方法之后,只是进入一个可运行状态,也把这种状态叫做就绪状态。
  • 正在运行(Running):处于可运行状态的线程,一旦获取了CPU的使用权,就可以立即进入正在运行状态。
  • 阻塞(Blocked):当线程受到了一些干扰的时候,就会进入阻塞状态,也就是它不在执行。
  • 终止(Dead)

    2、线程的声明周期,即线程从创建到启动,直至运行结束这段时间。也就是以上五个状态之间的相互转换过程。

    3、sleep方法的使用

  • Thread类中的方法 public static void sleep(long millis)

  • 休眠时间到了之后并不能让线程进入运行状态,只能进入一个可运行状态,可运行状态的线程只有获取带CPU的使用权之后,才能进入运行状态。
  • 作用:在指定的毫秒数内让正在执行的线程休眠(暂停执行、阻塞)。
  • 参数为休眠的时间,单位是毫秒。
  • 作用:可以用作计时器(有误差)、定期发送数据等。

    1. class MyThread implements Runnable {
    2. @Override
    3. public void run() {
    4. for (int i = 0; i < 15; i++) {
    5. System.out.println(Thread.currentThread().getName() + "正在运行" + i);
    6. try {
    7. Thread.sleep(1000);
    8. } catch (InterruptedException e) {
    9. e.printStackTrace();
    10. }
    11. }
    12. }
    13. }
    14. public class SleepTest {
    15. public static void main(String[] args) {
    16. MyThread myThread = new MyThread();
    17. Thread thread1 = new Thread(myThread, "线程1");
    18. thread1.start();
    19. Thread thread2 = new Thread(myThread, "线程2");
    20. thread2.start();
    21. }
    22. }

    4、Join方法应用

  • Thread类的方法:public final void join()/public final void join(long millis)

  • 作用:等待调用该方法的线程结束后才能执行/等待该线程终止的最长时间为millis毫秒 ```java class MyThread implements Runnable { @Override public void run() {
    1. for (int i = 0; i < 500; i++) {
    2. System.out.println(Thread.currentThread().getName() + "正在执行" + i);
    3. }
    } }

public class JoinDemo { public static void main(String[] args) { Thread thread = new Thread(new MyThread(), “我的线程1”); thread.start(); try { thread.join(2); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 30; i++) { System.out.println(“主线程运行第” + i + “次”); } } }

  1. <a name="w5hRI"></a>
  2. ## 四、线程的调度
  3. <a name="eRTI3"></a>
  4. #### 1、线程优先级
  5. - Java为线程优先级提供了10个优先级
  6. - 优先级可以用整数1-10表示,数字越大,表示有限级别越高;超过范围会抛出异常
  7. - 主线程默认优先级为5
  8. - 还可以用优先级常量表示
  9. - MAX_PRIORITY:线程的最高优先级10
  10. - MIN_PRIORITY:线程的最低优先级1
  11. - NORM_PRIORITY:线程的默认优先级5
  12. - 优先级相关的方法
  13. | 方法 | 说明 |
  14. | --- | --- |
  15. | publc int getPriority() | 获取线程优先级的方法 |
  16. | public void setPriority(int newPriority) | 设置线程优先级的方法 |
  17. ```java
  18. class MyThread extends Thread {
  19. private String name;
  20. public MyThread(String name) {
  21. this.name = name;
  22. }
  23. @Override
  24. public void run() {
  25. for (int i = 0; i < 50; i++) {
  26. System.out.println("线程" + name + "正在运行" + i);
  27. }
  28. }
  29. }
  30. public class PriorityDemo {
  31. public static void main(String[] args) {
  32. Thread thread1 = new Thread(new MyThread("1"));
  33. Thread thread2 = new Thread(new MyThread("2"));
  34. thread1.setPriority(10);
  35. thread2.setPriority(1);
  36. System.out.println("thread1 = " + thread1.getPriority());
  37. System.out.println("thread2 = " + thread2.getPriority());
  38. thread1.start();
  39. thread2.start();
  40. /* //获取主线程的优先级
  41. int priority = Thread.currentThread().getPriority();
  42. System.out.println("主线程的优先级:priority = " + priority);*/
  43. /* for (int i = 0; i < 15; i++) {
  44. System.out.println("主线程正在运行"+i);
  45. }*/
  46. }
  47. }

2、多线程运行问题

  • 各个线程 是通过竞争CPU时间而获得运行机会的
  • 各线程什么时候得到CPU时间,占用多久,是不可预测的。
  • 为了保证在存款和取款的时候,不宜徐其他线程对账户余额进行操作;需要将Bank对象进行锁定,使用synchronized实现,可以实现共享对象在同一个时刻只能被一个线程所访问。
  • synchronized关键字用在

    • 成员方法 : public synchronized void saveAccount()
    • 静态方法: public static synchronized void saveAccount()
    • 语句块 :synchronized (obj){......} 小括号里面是要被锁定的对象,大括号里面是要被同步的代码

      3、线程间的通信

  • 问题:账户余额不够了怎么办?等待存入足够的钱后处理?

  • wait()方法:中断线程的执行,使线程等待(阻塞状态)
  • notify()方法:唤醒等待的某一个线程,使其结束等待
  • notifyAll():唤醒所有处于等待状态的线程,使它们结束等待