• 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();
        }
    }
  • 相关阅读:
    文件操作实例加强
    文件操作的一般基础操作
    列表与if语句的结合
    难题记录
    字典,集合,列表混合使用需注意:
    列表的一些难度操作
    字符串知识巩固
    and与or的用法
    AngularJS中的过滤器
    NodeJS中的静态资源管理服务
  • 原文地址:https://www.cnblogs.com/vijay/p/3508055.html
Copyright © 2020-2023  润新知