Java多线程以及锁

线程

创建一个线程 相当于cpu开辟了独立的运行执行路径
每个执行路径都是独立空间
创建一个线程 该线程就会有一个独立栈空间
如果在同一个栈空间 不符合 先入栈的后出栈的规则

这里写图片描述

线程的六种状态:

  1. 新建状态(new 线程对象)
  2. 运行状态(调用start方法)
  3. 受阻塞状态(等待cpu的执行资源)
  4. 休眠状态(调用sleep(时间)方法)
  5. 等待状态(调用wait方法)
  6. 死亡状态(run方法执行完毕)

匿名内部类方式

相当于创建一个该类的子类的对象
new 父类名或接口名(){
    重写父类的方法
};
        /*
         * 使用匿名内部类方式
         * 创建线程的两种方式
         */

    public static void main(String[] args) {

        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + i);
                }
            }
        });
        thread.start();



        new Thread() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }.start();


    }

线程休眠

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            // 线程休眠1秒 单位毫秒
            Thread.sleep(666);
            System.out.println(Thread.currentThread().getName() + " - " + i);
        }
    }
class SleepThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            // 线程休眠1秒 单位毫秒
            // 如果子线程中 出现异常 只能try .. catch处理
            /*
             * thread类 是Runnable接口的 实现类
             * 重写接口中的 run
             * 该方法没有抛出异常
             * 所以所有Runnable接口的实现类(包括Thread类)
             * 都不能在run方法中抛出异常 只能处理
             */
            try {
                Thread.sleep(666);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " - " + i);
        }
    }
}

同步锁

锁可以是任意对象 要保证锁的唯一 多个线程使用的是同一把锁
 synchronized(对象锁) {

 }

同步锁规则:

线程 遇到锁 就进 同步代码块 (携带锁)
当线程 执行完代码块中的代码 把锁返还
线程 没有遇到锁 会在同步代码块外等着 遇到锁才能进
    卖火车票问题

    public static void main(String[] args) {

        tick tickets = new tick();
        Thread one = new Thread(tickets,"人工");
        Thread two = new Thread(tickets,"12306");
        Thread three = new Thread(tickets,"手机app");
        one.start();
        two.start();
        three.start();
    }



class Tickets implements Runnable{
    // 保证票是共享数据 只new一次该类对象
    private int num = 50;
    // 创建了对象锁 保证唯一
    Object mutex = new Object();
    @Override
    public void run() {
        while (true) {
            // 锁只要保证是对象和唯一就行 填this就行
            synchronized (this) {
                if (num > 0) {
                    // 线程休眠一会
                    try {
                        Thread.sleep(6);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "还剩" + num--);

                } else {
                    // 没票 结束循环
                    System.out.println("没票了");
                    break;
                }
            }
            // 让线程放弃cpu的资源
            Thread.yield();
        }
    }
}

    public static void main(String[] args) {
        tick tickets = new tick();
        Thread one = new Thread(tickets,"人工");
        Thread two = new Thread(tickets,"12306");
        Thread three = new Thread(tickets,"手机app");
        one.start();
        two.start();
        three.start();
    }


class tick implements Runnable{
    // 保证票是共享数据 只new一次该类对象
    private int num = 50; // 剩余票的数量
    // 创建了对象锁 保证唯一
    Object mutex = new Object();
    @Override
    public void run() {
        while (true) {
            if (sellTikes()) {
                break;
            } 
            // 让出系统资源
            Thread.yield();
        }

    }

    // 在方法中添加synchronized 关键词 把方法编程 同步方法
    public synchronized boolean sellTikes() {
        if (num > 0) {
            // 线程休眠一会
            try {
                Thread.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "还剩" + num--);
            return false;
        } else {
            // 没票 结束循环
            System.out.println("没票了");
            return true;
        }
    }
}

死锁

线程A当前持有互斥所锁lock1,线程B当前持有互斥锁lock2 接下来 当线程A仍然持有lock1时 它试图获取lock2 
因为线程B正持有lock2 因此线程A会阻塞等待线程B对lock2的释放 如果此时线程B在持有lock2的时候 
也在试图获取lock1 因为线程A正持有lock1 因此线程B会阻塞等待A对lock1的释放
二者都在等待对方所持有锁的释放 而二者却又都没释放自己所持有的锁
这时二者便会一直阻塞下去 这种情形称为死锁 
    模拟死锁


    public static void main(String[] args) {
        DeadThread deadThread = new DeadThread();
        Thread thread = new Thread(deadThread);
        Thread thread1 = new Thread(deadThread);
        thread.start();
        thread1.start();
    }


class LockA {
    // 私有构造方法
    private LockA() {
    }

    // 定义一个常量作为锁对象 不能修改
    public static final LockA LOCK_A = new LockA();

}

class LockB {
    private LockB() {
    }

    public static final LockB LOCK_B = new LockB();
}

class DeadThread implements Runnable{
    private boolean isTrue = true;
    @Override
    public void run() {
        while (true) {
            // 按标记
            if (isTrue) {
                // a ---> b
                synchronized (LockA.LOCK_A) {
                    System.out.println("if...LOCK_A");
                    synchronized (LockB.LOCK_B) {  
                        System.out.println("if...LOCK_B");  
                    }  
                }
            }else {
                // b ---> a
                synchronized (LockB.LOCK_B) {
                    System.out.println("if...LOCK_B");
                    synchronized (LockA.LOCK_A) {  
                        System.out.println("else...LOCK_A");  
                    }  
                }
            }
            // 修改标记
            isTrue = !isTrue;
        }

    }

}

Lock 接口

 使用locklock.lock();
  try{
        操作共享数据的代码
  } finally{
        lock.unlock();
  }
接口实现创建线程的好处:
避免了直接继承
Thread类的局限性(避免单继承)
    public static void main(String[] args) {
        Titkets3 titkets3 = new Titkets3();
        Thread t1 = new Thread(titkets3);
        Thread t2 = new Thread(titkets3);
        Thread t3 = new Thread(titkets3);
        t1.start();
        t2.start();
        t3.start();
    }


class Titkets3 implements Runnable{

    private int titkets = 50;
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true) {
            lock.lock();
            try {

                if (titkets > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " " + titkets--);
                } else {
                    break;
                }
            } finally {
                lock.unlock();
            }
            Thread.yield();
        }

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值