首页 > 代码库 > 线程高级应用-心得2-同步锁讲解及面试题案例分析

线程高级应用-心得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();
            }
        }
    }

}

 

线程高级应用-心得2-同步锁讲解及面试题案例分析