• 多线程和同步


    先说一下什么是多线程

    个人理解: 让几个方法同时执行(以极快速的在几个方法中切换)就是多线程

    实现多线程的方法

    1 继承thread类 重写run()方法

      (1)如代码所示

    public class A extends Thread{
        public void run() {
            
        }
    }

      (2)在主方法中创建A类的对象

    A a1 = new A("一号窗口");

      (3)调用a1对象的start方法

    a1.start();

    2实现runnable接口

    1 实现接口

    public class B implements Runnable  {
        //总票数
        private static int railway=30;
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                if(railway>0){    
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"卖了第"+railway--+"张火车票");
                }else{
                    System.out.println("票卖完了");
                    break;
                }
            }
        }

    2 创建对象  并创建线程对象 让对象作为线程对象的参数

    public static void main(String[] args) {
        B b = new B();
        Thread th1=new Thread(b,"窗口1");
        Thread th2=new Thread(b,"窗口2");
        Thread th3=new Thread(b,"窗口3");
        Thread th4=new Thread(b,"窗口4");
        th1.start();
        th2.start();
        th3.start();
        th4.start();
    }

    下面给出具体实现代码

      (1) 创建A类 把A类作为买火车票  run()方法中是客户买火车票

    public class A extends Thread{
    //把总票数设置成30 张 设置成静态的 共享变量
    private static int railway=30; /* * 卖火车票 * @see java.lang.Thread#run() */ public void run() { while(true) { if(railway>0){ try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(this.getName()+"卖了第"+railway--+"张火车票"); }else{ System.out.println("票卖完了"); break; } } } public A(String threadName){ super.setName(threadName); } public A(){} }

    (2) 创建主方法 在方法中创建对象  这里强调一下 几个线程就new几个对象  别一个对象start()多次 因为只有Start了才会执行多线程(不是立即执行 是等待cpu切换到才会执行)

    public static void main(String[] args) {
        A a1 = new A("一号窗口");    
        A a2 = new A("二号窗口");    
        A a3 = new A("三号窗口");    
        A a4 = new A("四号窗口");
        a4.start();
        a3.start();
        a2.start();
        a1.start();    
    }

    (3)运行结果

    二号窗口卖了第30张火车票
    三号窗口卖了第29张火车票
    一号窗口卖了第30张火车票
    .......口卖了第1张火车票 票卖完了 四号窗口卖了第2张火车票 票卖完了 一号窗口卖了第0张火车票 票卖完了 二号窗口卖了第
    -1张火车票 票卖完了

    那么问题来了 有同时买出一张票的 有把票卖多的  这是为什么呢 这里就要讲一下多线程的原理 就像电影一样  电影是一张一张的图片 以快速并且以一定的顺序播放 由于人眼的暂留特性和人脑补的的能力  就以为是在动  (脑补能力就是  汉字排序并一不定影响阅读顺序)

    多线程也是这样  Cpu在极快短的时间在几个线程中切换  速度达到一定程度  看起来就像几个线程在同时执行

    回到问题  因为线程1读取到总票数还有30张 还没有卖出去(没有进行--运算) 然后cpu切换到线2程  线程2也读取到了票数还有30并卖出(计算了--)cpu又切回线程1这时候线程1以为还有30张票并按30张卖了。(注 runnable接口原理一样)

    遇到问题解决问题 怎么解决这个问题呢  答案就是实现同步 关键字 synchronized 原理就是我操作共享数据的时候 别的线程要想操作 就让他等着

    实现同步的方法有很多种

    第一种 同步代码块

    格式

    synchronized(锁对象){同步的代码}

    具体代码

    public class A extends Thread{
        private static int railway=30;
        /*
         * 卖火车票
         * @see java.lang.Thread#run()
         */
        static Object obj=new Object();
        public void run() {
            while(true) {
    //同步代码块
                synchronized(obj){
                    if(railway>0){    
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        System.out.println(this.getName()+"卖了第"+railway--+"张火车票");
                    }else{
                        System.out.println("票卖完了");
                        break;
                    }
                }
            }
        }
        public A(String threadName){
            super.setName(threadName);
        }
        public A(){}
    }

    主方法代码没动

    public static void main(String[] args) {
        A a1 = new A("一号窗口");    
        A a2 = new A("二号窗口");    
        A a3 = new A("三号窗口");    
        A a4 = new A("四号窗口");
        a1.start();
        a2.start();
        a3.start();
        a4.start();    
    }

    运行结果

    一号窗口卖了第30张火车票
    一号窗口卖了第29张火车票
    一号窗口卖了第28张火车票
    一号窗口卖了第27张火车票
    一号窗口卖了第26张火车票
    一号窗口卖了第25张火车票
    一号窗口卖了第24张火车票
    四号窗口卖了第23张火车票
    四号窗口卖了第22张火车票
    四号窗口卖了第21张火车票
    四号窗口卖了第20张火车票
    四号窗口卖了第19张火车票
    四号窗口卖了第18张火车票
    四号窗口卖了第17张火车票
    四号窗口卖了第16张火车票
    四号窗口卖了第15张火车票
    三号窗口卖了第14张火车票
    三号窗口卖了第13张火车票
    三号窗口卖了第12张火车票
    三号窗口卖了第11张火车票
    三号窗口卖了第10张火车票
    三号窗口卖了第9张火车票
    三号窗口卖了第8张火车票
    三号窗口卖了第7张火车票
    二号窗口卖了第6张火车票
    二号窗口卖了第5张火车票
    二号窗口卖了第4张火车票
    二号窗口卖了第3张火车票
    三号窗口卖了第2张火车票
    四号窗口卖了第1张火车票
    票卖完了
    票卖完了
    票卖完了
    票卖完了

    注意点  锁对象一定要是几个线程共同拥有的  这里定义了一个静态变量作为锁对象  也可以用别的

    第二种方法 synchronized 修饰普通方法和多个代码块

    public class A extends Thread {
        private static int railway = 30;
        /*
         * 卖火车票
         * 
         * @see java.lang.Thread#run()
         */
        static Object obj = new Object();
        static int i = 0;
    
        public void run() {
            while (railway > 0) {
    
                if (i % 2 == 0) {
    //代码块1
    synchronized (obj) { aa();
                i++; } }
    else {

    //代码块2
    synchronized (obj) { aa();
                i++; } } } }
    public synchronized void aa() { if (railway > 0) { // Thread.currentThread()为获取线程名字 System.out.println(Thread.currentThread().getName() + "卖了第" + railway-- + "张火车票"); } else { System.out.println("票卖完了"); } } public A(String threadName) { super.setName(threadName); } public A() { } }

    运行结果

    一号窗口卖了第30张火车票
    四号窗口卖了第29张火车票
    四号窗口卖了第28张火车票
    四号窗口卖了第27张火车票
    四号窗口卖了第26张火车票
    四号窗口卖了第25张火车票
    四号窗口卖了第24张火车票
    四号窗口卖了第23张火车票
    四号窗口卖了第22张火车票
    四号窗口卖了第21张火车票
    四号窗口卖了第20张火车票
    四号窗口卖了第19张火车票
    四号窗口卖了第18张火车票
    四号窗口卖了第17张火车票
    四号窗口卖了第16张火车票
    四号窗口卖了第15张火车票
    四号窗口卖了第14张火车票
    四号窗口卖了第13张火车票
    四号窗口卖了第12张火车票
    四号窗口卖了第11张火车票
    四号窗口卖了第10张火车票
    四号窗口卖了第9张火车票
    四号窗口卖了第8张火车票
    四号窗口卖了第7张火车票
    四号窗口卖了第6张火车票
    四号窗口卖了第5张火车票
    四号窗口卖了第4张火车票
    四号窗口卖了第3张火车票
    四号窗口卖了第2张火车票
    四号窗口卖了第1张火车票
    票卖完了
    票卖完了
    票卖完了

    多个代码块之间要实现同步 则锁对象必须是同一个

  • 相关阅读:
    idea 字体大小设置
    idea单窗口管理多个工程项目
    java迭代器使用(修改元素的值)
    idea自动保存设置+确保修改正确
    服务器暂时无法处理您的请求,请稍后重试。解决方法
    [C#] IpcChannel双向通信,参考MAF的AddInProcess开发插件,服务断开重新打开及服务生存周期管理
    XE10.4.2 IDE关闭LSP
    delphi 色彩搭配,HSV与RGB转换
    金额转大写 (delphi)
    MMDet 踩坑
  • 原文地址:https://www.cnblogs.com/guoyafenghome/p/8537061.html
Copyright © 2020-2023  润新知