两种创建线程的方式/线程的生命周期及各自使用同步锁时的区别

好记性不如赖笔头…………

线程的生命周期:

1.新建:使用new创建对象,
2.准备就绪:调用了start()方法,但还没有抢占到CPU资源
3.运行:调用了start()方法并抢占到了cpu资源,开始执行
4.阻塞:调用 sleep()/wait()方法,使线程让出CPU资源并进入休眠状态,可调用notity()方法使线程进入到准备就绪状态
5.销毁:run方法执行结束或调用 stop()方法后,线程已经不在使用,成为了垃圾线程,将GC回收

两种创建线程的方法在使用同步锁的区别

  1. 实现了Runnable接口的类创建线程:
    因在创建多个线程时,实现Runnable接口的类只须要创建一个,所以它的锁对象默认为 this
  2. 继承了Thread类的类,在创建线程时,如果使用了同步锁,那么它默认锁对象默认为 类名.class,原因在于继承了Thread的类在创建线程时,每创建一个线程创建了一个新的对象,要保证它的锁是固定的,所以它的默认锁对象就是 类名.class
------------------------------------------------------------------继承Thread的实体类Apples------------------------------------------------------------------

package com.Ckinghan.thread;

/**
 * @author Ckinghan
 *  @描述:如果类继承了Thread类,那么它在使用同步锁时,锁的对象及共享数据必须是静态的(即类对象,不管这个类被new几个,类对象只有一个)
 *              当锁加在方法上时,它的默认对象是类名.class,如Apples类在方法上加锁时,它的默认锁对象是Apples.class
 */
public class Apples extends Thread{

    public Apples(String threadName){
        super(threadName);
    }

    /**
     * 共享数据变量,必须使用static修饰,否则,在创建线程时每一个线程都会有一个apples,且初始值都是100,就有了加锁的必要,也与
     * 最初的设计不符
     */
    private static Integer apples = 100;

    /**
     * 锁的对象,必须是被static修饰的且不管类被new多少个,它始终只能有一个且是不变的,否则,同步锁将失效
     */
    public static Integer lockObject = new Integer(0);

    @Override
    public void run() {
        while (true) {
            if(apples % 3 == 0){
                /**
                 * 同步锁块的锁对象,建议使用 类名.class(在本类中即:Apples.class)
                 */
                synchronized (Apples.class) {
                    if(apples > 0){
                        /**
                         * 使线程休眠30毫秒,增加出现并发的机率
                         */
                        try {
                            Thread.sleep(30);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(this.getName()+"抢到了编号为"+apples--+"的苹果");
                    }else{
                        System.out.println("苹果已经被抢完了");
                        break;
                    }
                }
            }else if(apples % 3 ==1){
                /**
                 * 同步锁块的锁对象,建议使用 类名.class(在本类中即:Apples.class)
                 */
                synchronized (Apples.class) {
                    if(apples > 0){
                        /**
                         * 使线程休眠30毫秒,增加出现并发的机率
                         */
                        try {
                            Thread.sleep(30);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(this.getName()+"抢到了编号为"+apples--+"的苹果");
                    }else{
                        System.out.println("苹果已经被抢完了");
                        break;
                    }
                }           
            }else{
                //抢苹果
                lockFunction();
            }//if end
        }//while end    
    }

    public synchronized static void lockFunction(){
        if(apples > 0){
            System.out.println(Thread.currentThread().getName()+"抢到了编号为"+apples--+"的苹果");
            return;
        }
        System.out.println("苹果已经被抢完了");
    }
}


------------------------------------------------------------------实现了Runnable接口的实体类Apple------------------------------------------------------------------

package com.Ckinghan.thread;

/**
 * 创建线程的第二种方式 :实现Runnable
 * 在使用同步锁时,如果同步锁加在方法上,它默认的锁对象是this
 * 如果用在同步锁块上,它的锁对象可以自己定义,建议使用this,
 * @author Ckinghan
 *  @描述:
 */
public class Apple implements Runnable {

    private Integer apples = 100;

    @Override
    public void run() {
        while(true){
            if(apples % 4 == 0){
                synchronized (this) {
                    if(apples > 0){
                        try {
                            Thread.sleep(30);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"抢到了编号为"+apples--+"的苹果");
                    }else{
                        System.out.println("苹果已经被抢完了");
                        break;
                    }
                }
            }else {
                //调用同步锁的方法抢苹果
                lockFunction();
            }


        }

    }

    /**
     * @描述:实现Runnable接口的类,在方法上加同步锁时,默认的锁对象为this
     * @创建时间:
     */
    private synchronized void  lockFunction(){
        if(apples > 0){
            System.out.println(Thread.currentThread().getName()+"抢到了编号为"+apples--+"的苹果");
            return;
        }
        System.out.println("苹果已经被抢完了");
    }

}


------------------------------------------------------------------测试Demo------------------------------------------------------------------

package com.Ckinghan.thread;

public class ApplesDemo {

    public static void main(String[] args) {
        /**
         *   * @描述:几个小朋友抢苹果,为防止一个编号的苹果被多个人同时抢中,加同步锁
         *              因为apple实现了Runnable接口,鉴于它的线程创建方式,在加锁时,
         *              锁的对象建议使用this,因为在方法上加同步锁,它的默认锁对象是this
         */
//      threadRunnableApple();



        /**
         * @描述:几个小朋友抢苹果,为防止一个编号的苹果被多个人同时抢中,加同步锁
         *              因为apples继承了Thread类,鉴于它的线程创建方式,在加锁时,
         *              锁的对象建议使用 类名.class,因为在方法上加同步锁,它的默认锁对象是 类名.clss(如Apples.class)
         */
        extendsThreadApple();

    }

    /**
     * @描述:几个小朋友抢苹果,为防止一个编号的苹果被多个人同时抢中,加同步锁
     *              因为apples继承了Thread类,鉴于它的线程创建方式,在加锁时,
     *              锁的对象建议使用 类名.class,因为在方法上加同步锁,它的默认锁对象是 类名.clss(如Apples.class)
     * @创建时间:
     */
    public static void extendsThreadApple(){
        /**
         * 创建四个线程
         */
        Apples persion1 = new Apples("小明");
        Apples persion2 = new Apples("小二");
        Apples persion3 = new Apples("小黄");
        Apples persion4 = new Apples("小三");
        /**
         * 启动线程
         */
        persion1.start();
        persion2.start();
        persion3.start();
        persion4.start();
    }

    /**
     * @描述:几个小朋友抢苹果,为防止一个编号的苹果被多个人同时抢中,加同步锁
     *              因为apple实现了Runnable接口,鉴于它的线程创建方式,在加锁时,
     *              锁的对象建议使用this,因为在方法上加同步锁,它的默认锁对象是this
     * @创建时间:
     */
    public static void threadRunnableApple(){
        /**
         * 注意,实现了Runnable接口的apple类对象创建线程时,因为apple类只实例化了一次,所以不用静态的锁对象就可以,因它多个线程使用
         * 的对象只有apple一个
         */
        Apple apple = new Apple();
        /**
         * 创建四个线程
         */
        Thread persion1 = new Thread(apple,"小明");
        Thread persion2 = new Thread(apple,"小二");
        Thread persion3 = new Thread(apple,"小黄");
        Thread persion4 = new Thread(apple,"小三");
        /**
         * 启动线程
         */
        persion1.start();
        persion2.start();
        persion3.start();
        persion4.start();

    }

}

------------------------------------------------------------------执行结果:------------------------------------------------------------------

小明抢到了编号为100的苹果
小三抢到了编号为99的苹果
小黄抢到了编号为98的苹果
小黄抢到了编号为97的苹果
小黄抢到了编号为96的苹果
小黄抢到了编号为95的苹果
小二抢到了编号为94的苹果
小二抢到了编号为93的苹果
小二抢到了编号为92的苹果
小黄抢到了编号为91的苹果
小三抢到了编号为90的苹果
小三抢到了编号为89的苹果
小明抢到了编号为88的苹果
小明抢到了编号为87的苹果
小明抢到了编号为86的苹果
小三抢到了编号为85的苹果
小黄抢到了编号为84的苹果
小二抢到了编号为83的苹果
小黄抢到了编号为82的苹果
小三抢到了编号为81的苹果
小明抢到了编号为80的苹果
小明抢到了编号为79的苹果
小三抢到了编号为78的苹果
小三抢到了编号为77的苹果
小二抢到了编号为76的苹果
小二抢到了编号为75的苹果
小二抢到了编号为74的苹果
小黄抢到了编号为73的苹果
小二抢到了编号为72的苹果
小二抢到了编号为71的苹果
小二抢到了编号为70的苹果
小二抢到了编号为69的苹果
小二抢到了编号为68的苹果
小明抢到了编号为67的苹果
小三抢到了编号为66的苹果
小三抢到了编号为65的苹果
小明抢到了编号为64的苹果
小二抢到了编号为63的苹果
小二抢到了编号为62的苹果
小黄抢到了编号为61的苹果
小黄抢到了编号为60的苹果
小黄抢到了编号为59的苹果
小二抢到了编号为58的苹果
小明抢到了编号为57的苹果
小明抢到了编号为56的苹果
小三抢到了编号为55的苹果
小三抢到了编号为54的苹果
小三抢到了编号为53的苹果
小明抢到了编号为52的苹果
小二抢到了编号为51的苹果
小二抢到了编号为50的苹果
小黄抢到了编号为49的苹果
小黄抢到了编号为48的苹果
小黄抢到了编号为47的苹果
小二抢到了编号为46的苹果
小二抢到了编号为45的苹果
小二抢到了编号为44的苹果
小明抢到了编号为43的苹果
小明抢到了编号为42的苹果
小明抢到了编号为41的苹果
小三抢到了编号为40的苹果
小三抢到了编号为39的苹果
小三抢到了编号为38的苹果
小明抢到了编号为37的苹果
小明抢到了编号为36的苹果
小明抢到了编号为35的苹果
小二抢到了编号为34的苹果
小二抢到了编号为33的苹果
小黄抢到了编号为32的苹果
小二抢到了编号为31的苹果
小黄抢到了编号为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的苹果
苹果已经被抢完了
苹果已经被抢完了
苹果已经被抢完了
苹果已经被抢完了
苹果已经被抢完了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值