学习笔记_多线程

本章要点:

  • 多线程的运行原理
  • 创建多线程的两种方式
  • 能过说出多线程的六种状态
  • 能够解决线程安全问题

多线程的运行原理

  同一时间内,CPU只能处理1条线程,只有1条线程在工作(执行);多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换)。如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象。

创建多线程的两种方式:

  1. 继承Thread类,调用start()方法

  2. 实现Runnable接口

代码如下:

  自定义线程类

/**
 * @author 阿豪
 * @Date 2019-5-27
* 自定义线程类
*/ public class ThreadDemo_01 extends Thread{ /** * 重写run方法,用于线程执行的操作 */ @Override public void run() { for (int i = 0; i < 20;i++) { System.out.println("自定义线程运行第 " + i + ""); } } }

   测试类

/**
 * @author 阿豪
 * @Date 2019-5-27
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        //创建Thread对象
        Thread thread = new ThreadDemo_01();
        //开启自定义线程
        thread.start();

        //定义主线程执行操作
        for (int i = 0; i < 20; i++) {
            System.out.println("主线程运行第" + i + "次");
        }
    }
}

线程安全问题

  为什么会出现线程安全问题?

  拿火车站售票举例:

    假设总共100张火车票,总共有3个窗口(即3个线程)共同售票,当其中一个窗口已经卖完最后一张票的时候,其他的两个窗口并不知情,继续售卖,结果就会导致出现问题.所以就是线程不安全的问题

  那么,如何解决线程安全问题呢?

  有三种方法

    1. 同步代码块

    2. 同步方法

    3. lock锁

  1. 同步代码块:

    synchronized(锁对象){  

      //可能会发生错误的代码

    }

注意:

  锁对象:

    1. 锁对象必须被所有线程所共享,即锁对象是唯一的

    2. 锁对象可以是任意对象

public class MyThread  implements Runnable {
    //总共有100张火车票
    private int ticket = 100;

    /**
     * 卖票的方法
     */
    @Override
    public void run() {
        while (true) {
            synchronized (MyThread.class) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket + "票");
                        ticket--;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println("票卖完了");
                    break;
                }
            }
        }
    }
}

  2. 同步方法

    将可能发生线程安全问题的代码封装成一个方法,这个方法要加上synchronized来修饰

public class MyThread  implements Runnable {
    //总共有100张火车票
    private int ticket = 100;
    boolean flag;
    /**
     * 卖票的方法
     */
    @Override
    public void run() {
        flag = true;
        while (flag) {
            method();
        }
    }

    public synchronized void method(){
        synchronized (MyThread.class) {
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket + "票");
                    ticket--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("票卖完了");
                flag = false;
            }
        }
    }
}

  3. 方式三:Lock锁

public class MyThread implements Runnable {
    //总共有100张火车票
    private int ticket = 100;
    //创建look类的子类ReentrantLock, 然后在可能出现线程安全问题的代码前调用lock()方法
    Lock look = new ReentrantLock();

    /**
     * 卖票的方法
     */
    @Override
    public void run() {
        while (true) {
            //在可能发生线程安全问题的代码之前, 调用lock()方法
            look.lock();
            try {
                if (ticket > 0) {
                    Thread.sleep(100);
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket + "票");
                    ticket--;
                } else {
                    System.out.println("票卖完了");
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //释放lock()方法 -- unlock()  放在可能发生线程安全问题的代码后
                look.unlock();
            }

        }

    }
}

测试类:

/**
 * @author 阿豪
 * @Date 2019-5-27
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        Thread t = new Thread(mt);
        Thread t2 = new Thread(mt);
        Thread t3 = new Thread(mt);
        t.start();
        t2.start();
        t3.start();
    }
}

多线程的六种状态:

  1. NEW      : 线程刚被创建, 但是未被启动

  2. RUNNABLE  : 可运行jvm里的状态

  3. BLOCKED    : 阻塞状态

  4. WAITING    : 无线等待

  5. TIMEWAITING : 计时等待

  6. TEMINATED  : 被终止 (因run()方法执行完成, 正常终止)

 
原文地址:https://www.cnblogs.com/myBlog-ahao/p/10932742.html