zoukankan      html  css  js  c++  java
  • Day7:多线程

    今天记录Java中最重要的一个知识点------多线程!!!

    进程:就是应用程序在内存中分配的空间。(正在运行中的程序)
        
    
    线程:是进程中负责程序执行的执行单元。也称为执行路径。
        一个进程中至少有一个线程在负责该进程的运行。
        如果一个进程中出现了多个线程,就成该程序为多线程程序。
    
    
    举例:运动场--鸟巢。水立方。
    
    多线程技术:解决多部分代码同时执行的需求。合理的使用cpu资源。
    /*
    多线程的运行根据cpu的切换完成的。怎么切换cpu说的算,
    所以多线程运行有一个随机性(cpu的快速切换造成的)。
    
    jvm中的多线程。
    至少有两个线程:一个是负责自定义代码运行的。这个从main方法开始执行的线程称之为主线程。
                一个是负责垃圾回收的。
    
    通过实验,会发现每次结果不一定相同,因为随机性造成的。
    
    而且每一个线程都有运行的代码内容。这个称之为线程的任务。
    之所以创建一个线程就是为了去运行制定的任务代码。
    
    而线程的任务都封装在特定的区域中。
    比如:
    主线程运行的任务都定义在main方法中。
    垃圾回收线程在收垃圾都会运行finalize方法。
    
    */
    
    class Demo
    {
        //定义垃圾回收方法。
        public void finalize()
        {
            System.out.println("demo ok");
        }
    }
    
    class  FinalizeDemo
    {
        public static void main(String[] args) 
        {
    
            System.gc();//启动垃圾回收器。
            new Demo();
            new Demo();
            new Demo();
            System.out.println("Hello World!");
        }
    }
    /*
    
    final , finally , finalize有什么区别?
    
    */

    /*
    如何建立一个执行路径呢?
    
    通过查阅api文档 java.lang.Thread类。
    该类的描述中有创建线程的两种方式:
    1,继承Thread类。
        1,继承Thread类。
        2,覆盖run方法。
        3,创建子类对象就是创建线程对象。
        4,调用Thread类中的start方法就可以执行线程。并会调用run方法。
    
        start()开启线程后,都会执行run方法。说明run方法中存储的是线程要运行的代码。
        所以,记住,自定义线程的任务代码都存储在run方法中。
    
    */
    class Demo extends Thread
    {
        private String name;
        Demo(String name)
        {
            //super();
            this.name = name;
        }
    
        //覆盖run方法。
        public void run()
        {
            for(int x=1; x<=40; x++)
            {
    
                System.out.println(this.getName()+"....."+name+"...."+x);
                System.out.println(Thread.currentThread().getName()+"....."+name+"...."+x);
            }
        }
        
    }
    
    /*
    调用start和调用run方法的区别?
    调用start会开启线程,让开启的线程去执行run方法中的线程任务。
    直接调用run方法,线程并未开启,去执行run方法的只有主线程。
    
    */
    class  ThreadDemo
    {
        public static void main(String[] args) 
        {
            Demo d1 = new Demo("张三");//Thread-0
            Demo d2 = new Demo("麻子");
            d1.start();//start():两件事:1,开启线程,2,调用run方法。
            d2.start();
    
            for(int x=1; x<40; x++)
            {
                System.out.println(Thread.currentThread().getName()+"--------"+x);
            }
        }
    }

    经典实例:卖票

    class SaleTicket extends  Thread
    {
        private  int tickets = 100;//
    
        //卖票的代码需要被多个线程执行,所以要将这些代码定义在线程任务中。run方法。
        public void  run()
        {
            while(true)
            {
                if(tickets>0)
                {
                    System.out.println(Thread.currentThread().getName()+"...."+tickets--);
                }
            }
        }
    }
    
    
    class  TicketDemo
    {
        public static void main(String[] args) 
        {
            //创建四个线程。会创建400张票。不合适,不建议票变成静态的,所以如何共享这100张票。需要将资源和线程分离。
                //到api中查阅了第二创建线程的方式。
            SaleTicket t1 = new SaleTicket();
            SaleTicket t2 = new SaleTicket();
            SaleTicket t3 = new SaleTicket();
            SaleTicket t4 = new SaleTicket();
            t1.start();
            t1.start();
            t1.start();
            t1.start();
        }
    }
    /*
    创建线程的第二种方式。实现Runnable接口。
    1,定义一个类实现Runnable。
    2,覆盖Runnable接口中的run方法,将线程要运行的任务代码存储到该方法中。
    3,通过Thread类创建线程对象,并将实现了Runnable接口的对象作为Thread类的构造函数的参数进行传递。
    4,调用Thread类的start方法,开启线程。
    
    
    
    实现Runnble接口的好处:
    1,避免了继承Thread类的单继承的局限性。
    2,Runnable接口出现更符合面向对象,将线程单独进行对象的封装。
    3,Runnable接口出现,降低了线程对象和线程任务的耦合性。
    所以,以后创建线程都使用第二种方式。
    
    
    */
    
    class SaleTicket implements Runnable
    {
        private int tickets = 100;
        public void run()
        {
            while(true)
            {
                if(tickets>0)
                {
                    System.out.println(Thread.currentThread().getName()+"...."+tickets--);
                }
            }
        }
    }
    
    class TicketDemo2 
    {
        public static void main(String[] args) 
        {
            //线程任务对象。
            SaleTicket t = new SaleTicket();
    
            //创建四个线程。通过Thread类对象。
            Thread t1 = new Thread(t);
            Thread t2 = new Thread(t);
            Thread t3 = new Thread(t);
            Thread t4 = new Thread(t);
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            
        }
    }

    /*
    两个储户,到同一个银行存钱,每个人存了3次,一次100元。
    1,描述银行。
    2,描述储户任务。
    
    分析多线程是否存在安全隐患。
    
    1,线程任务中是否有共享的数据。
    2,是否多条操作共享数据的代码。
    
    
    
    
    */
    class Bank
    {
        private int sum;
        private Object obj = new Object();
        public void add(int n)
        {
            synchronized(obj)
            {
                sum = sum + n;
                try{Thread.sleep(10);}catch(Exception e){}
                System.out.println("sum="+sum);
            }
        }
    }
    class Customer implements Runnable
    {
        private    Bank b = new Bank();
        public void run()
        {
            for(int x=0; x<3; x++)
            {
                b.add(100);
            }
        }
    }
    
    class ThreadTest 
    {
        public static void main(String[] args) 
        {
            //1,创建任务对象。
            Customer c = new Customer();
            Thread t1 = new Thread(c);
            Thread t2 = new Thread(c);
            t1.start();
            t2.start();
        }
    }
    /*
    多线程的安全问题。
    
    产生的原因:
    1,线程任务中有处理到共享的数据。
    2,线程任务中有多条对共享数据的操作。
    一个线程在操作共享数据的过程中,其他线程参与了运算,造成了数据的错误。
    
    
    解决的思想:
    只要保证多条操作共享数据的代码在某一时间段,被一条线程所执行,
    在执行期间不允许其他线程参与运算。
    
    
    咋保证呢?
    用到了同步代码块。
    synchronized(对象)
    {
        需要被同步的代码。
    }
    
    同步在目前情况下保证了一次只能有一个线程在执行。其他线程进不来。
    这就是同步的锁机制。
    
    
    好处:解决了多线程的安全问题。
    
    弊端:减低效率。
    
    
    有可能出现这样一种情况:
    多线程安全问题出现后,加入了同步机制,没有想到,安全问题依旧!咋办。
    
    这时肯定是同步出了问题。
    
    只要遵守了同步的前提,就可以解决。
    
    同步的前提:
        多个线程在同步中必须使用同一个锁。这才是对多个线程同步。
    
    
    
    
    */
    
    class SaleTicket implements Runnable
    {
        private int tickets = 100;
        Object obj = new Object();
        public void run()
        {
            while(true)
            {
                synchronized(obj)
                {
                    if(tickets>0)
                    {    
                        try{Thread.sleep(10);}catch(InterruptedException e){}//让线程到这里稍微停一下。
                        System.out.println(Thread.currentThread().getName()+"...."+tickets--);
                    }
                }
            }
        }
    }
    
    
    class TicketDemo3 
    {
        public static void main(String[] args) 
        {
            SaleTicket t = new SaleTicket();
    
            //创建四个线程。通过Thread类对象。
            Thread t1 = new Thread(t);
            Thread t2 = new Thread(t);
            Thread t3 = new Thread(t);
            Thread t4 = new Thread(t);
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    }
  • 相关阅读:
    VysorPro助手
    Play 2D games on Pixel running Android Nougat (N7.1.2) with Daydream View VR headset
    Play 2D games on Nexus 6P running Android N7.1.1 with Daydream View VR headset
    Native SBS for Android
    ADB和Fastboot最新版的谷歌官方下载链接
    How do I install Daydream on my phone?
    Daydream Controller手柄数据的解析
    蓝牙BLE传输性能及延迟分析
    VR(虚拟现实)开发资源汇总
    Android(Java)控制GPIO的方法及耗时分析
  • 原文地址:https://www.cnblogs.com/vijay/p/3508055.html
Copyright © 2011-2022 走看看