zoukankan      html  css  js  c++  java
  • 学习笔记_多线程

    本章要点:

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

    多线程的运行原理

      同一时间内,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()方法执行完成, 正常终止)

     
  • 相关阅读:
    uva 10369 Arctic Network
    uvalive 5834 Genghis Khan The Conqueror
    uvalive 4848 Tour Belt
    uvalive 4960 Sensor Network
    codeforces 798c Mike And Gcd Problem
    codeforces 796c Bank Hacking
    codeforces 768c Jon Snow And His Favourite Number
    hdu 1114 Piggy-Bank
    poj 1276 Cash Machine
    bzoj 2423 最长公共子序列
  • 原文地址:https://www.cnblogs.com/myBlog-ahao/p/10932742.html
Copyright © 2011-2022 走看看