zoukankan      html  css  js  c++  java
  • 线程高级应用-心得2-同步锁讲解及面试题案例分析

    1.引入同步锁

    2.同步锁案例分析

    package com.itcast.family;
    
    /*
     * 传统线程的使用及注意事项
     */
    public class TraditionalThread {
    
        public static void main(String[] args) {
            
            //一、线程1;直接new一个thread子类,让子类run方法覆盖父类的run()
            Thread thread1 = new Thread(){
                
                @Override
                public void run() {
                    while(true){
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //线程1获取到的线程名字是从0开始的,即thread1--1:Thread-0
                        System.out.println("thread1--1:"+Thread.currentThread().getName());
                        //在这里this 即代表thread对象,因为直接new的是thread类
                        System.out.println("thread1--2:"+this.getName());
                    }
                }
                
            };
            thread1.start();
            /*
             * 运行结果:
             * thread1--1:Thread-0
               thread1--2:Thread-0
             */
            
            
            
            //二、线程2;不new子类,给Thread类传一个Runnable参数的构造方法
            Thread thread2 = new Thread(new Runnable(){
    
                @Override
                public void run() {
                    while(true){
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("thread2--1:"+Thread.currentThread().getName());
                        /*这里就不能用this了,this在这里代表Runable对象,不是Thread线程对象了,
                         * Runable是线程运行的代码宿主;所以要想获取该线程的名字一般都是用
                         * Thread.currentThread().getName();而不是this.getName()
                         */
    //                    System.out.println("thread2--2:"+this.getName());
                    }
                }
                
            });
            thread2.start();
            /*
             * 运行结果:
             * thread2--1:Thread-1
                thread1--1:Thread-0
               thread1--2:Thread-0
             */
            
            /*
             * 以上两种new 线程的方法有什么不同?
             *   第一种是new Thread线程对象,通过子类覆盖父类run()方法来达到需求;
             *   第二种是实现线程的构造方法,构造方法传入一个Runnable参数,实现其run().
             *   
             * 为什么大多数人都是使用第二种方法,而不是第一种?
             *   第二种方法更符合面向对象的思想 ;第二种方法把线程中运行的代码放到了一个Runnable对象中,
             *   固更加体现面向对象的思维;固使用第二种的方法比较普遍,更自然
             */
            
            
            //三、线程3;以下代码使用的是Thread中的run方法,而不是Runnable中的run方法
            /*
             * 原因:  
             *   如果不覆盖父类的run方法就以父类的run方法为主,如果覆盖了就以子类覆盖的run方法为主;
             *   父类的构造方法回去找Runnable中的run方法,所以这里的runnable不会执行
             */
            new Thread(new Runnable(){
                @Override
                public void run() {
                    while(true){
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("thread3--Runnable:"+Thread.currentThread().getName());
                    }
                }
            }){
                @Override
                public void run() {
                    while(true){
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("thread3--Thread:"+Thread.currentThread().getName());
                    }
                }
                }.start();
        }
        
        
        /*
         *  单线程比多线程快,性能更低;因为多线程之间的切换也要费时间,cpu只有一个
         *  比如:
         *      1、做馒头,我在一个桌子做馒头比在三个桌子做馒头快;看起来三个桌子都在产生馒头,
         *    但你在这三个桌子间来回走动也费时间;
         *      2、下载东西的时候为什么下载多个比下载一个快,这不是计算机本身加速了,
         *    而是服务器给你分了其他人的带宽,简单的说就是你抢了别人的网速;
         *      3、从u盘上把电脑上拷东西,考一个文件夹要不比分别考改文件下的子文件夹快。
         */
    }
    3.定时器案例分析及知识点应用
    package com.itcast.family;
    
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    /*
     * 定时器Timer的使用
     */
    public class TraditionalTimer {
    
        
        //将其声明在此处是因为,内部类和方法内部不能声明静态变量
        private static int count = 0;
        public static void main(String[] args) {
    
            /*
             * Timer:定时器schedule:调度Task:任务
             */
    
            /*
             * 1.一个简单的连环炸弹定时器,初步 new Timer().schedule(new TimerTask() {
             * 
             * @Override public void run() { System.out.println("bombing!"); } },
             * 6000, 3000); //用线程是为了显示休眠时间,隔1秒输出一个时间秒 while(true){
             * System.out.println(new Date().getSeconds()); try {
             * Thread.sleep(1000); } catch (InterruptedException e) {
             * e.printStackTrace(); } }
             */
            
            
    
            /*
             * 2.制造不同间隔交替执行的定时器,这是引出下面知识点的引子
             * new Timer().schedule(new TimerTask() {
    
                @Override
                public void run() {
                    System.out.println("bombing!");
                    new Timer().schedule(
                                         * new TimerTask() {
                                         * 
                                         * @Override public void run() {
                                         * System.out.println("bombing!"); } }
                                         * 
                                         * 内部再嵌套Timer的运行结果:33 34 35 36 37 38
                                         * bombing! 39 40 bombing! 41 bombing! 42 43
                                         * bombing! 44
                                         this
                                                 * 使用this代替再次Timer类放入运行结果:
                                                 * 52 53 54 55 56 57 bombing! 58
                                                 * Exception in thread "Timer-0"
                                                 * java.lang.IllegalStateException:
                                                 * Task already scheduled or
                                                 * cancelled
                                                 *   分析:会出现定时器无法再调度的结果,因为这是匿名内部类
                                                 *   只能执行一次,不能循环执行
                                                 , 2000);
                }
            }, 6000, 3000);
            // 用线程是为了显示休眠时间,隔1秒输出一个时间秒
            while (true) {
                System.out.println(new Date().getSeconds());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }*/
    
            
            //3.优化交替执行定时器代码:比如:一个2分钟爆炸一回一个4分钟爆炸一回
            class MyTimerTask extends TimerTask{
    
                @Override
                public void run() {
                    count = (count+1) % 2;
                    System.out.println("bombing");
                    new Timer().schedule(new MyTimerTask(), 2000+2000*count);
                }}
            
            new Timer().schedule(new MyTimerTask(),2000);
            while (true) {
                System.out.println(new Date().getSeconds());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
  • 相关阅读:
    1. Java基础知识
    2. HelloWorld
    3. Java基础语法
    4. Java流程控制
    设计一个有getMin功能的栈
    ASP.NET中Cookies的使用
    用sql语句建表
    Eclipse “cannot be resolved to a type” 错误
    使用java连接sqlserver2008 R2/sqlserver2008
    使用java连接MySQL数据库
  • 原文地址:https://www.cnblogs.com/cxxjohnson/p/6261887.html
Copyright © 2011-2022 走看看