JAVA高级应用之线程详解

JAVA高级应用之线程详解

线程的六种状态

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

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

这里写图片描述

代码示例
package com.lanou3g.p02;

public class Demo08 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int i = 1; i < 50; i++) {
            System.out.println(Thread.currentThread().getName() + "-" + i);
        }
    }
}

匿名内部类创建线程

匿名内部类方式 
相当于创建了一个该类的子类的对象
new 父类名()或接口名{
    重写父类的方法
}
这里new出来的 就是这个类的 子类对象
对学生进行排序-方法一
public class Demo09 {
    public static void main(String[] args) {
        TreeSet<Student> set = new TreeSet<>(new MyComparator());
        set.add(new Student("张飞", 20));
        set.add(new Student("关羽",10));
        set.add(new Student("刘备", 15));
        for (Student student : set) {
            System.out.println(student);
        }
    }
}
class MyComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        // TODO Auto-generated method stub
        return o1.getAge() - o2.getAge();
    }
}
对学生进行排序-方法二
public class Demo09 {
    public static void main(String[] args) {
        Comparator<Student> comparator = new Comparator<Student>() {

            @Override
            public int compare(Student o1, Student o2) {
                // TODO Auto-generated method stub
                return o1.getAge() - o2.getAge();
            }

        };
        TreeSet<Student> set = new TreeSet<>(comparator);
        set.add(new Student("张飞", 20));
        set.add(new Student("关羽",10));
        set.add(new Student("刘备", 15));
        for (Student student : set) {
            System.out.println(student);
        }
    }
}
对学生进行排序-方法三
public class Demo09 {
    public static void main(String[] args) {
        TreeSet<Student> set = new TreeSet<>(
                new Comparator<Student>() {

                    @Override
                    public int compare(Student o1, Student o2) {
                        // TODO Auto-generated method stub
                        return o1.getAge() - o2.getAge();
                    }
        });
        set.add(new Student("张飞", 20));
        set.add(new Student("关羽",10));
        set.add(new Student("刘备", 15));
        for (Student student : set) {
            System.out.println(student);
        }
    }
}

创建线程的三种方式

方式一
public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println(Thread.currentThread().getName() + "我是方式一");
            }
        };
        thread.start();
    }
public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println(Thread.currentThread().getName() + "我是方式一");
            }
        }.start();;
    }
方式二
public static void main(String[] args) {
    Runnable runnable = new Runnable() {        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            System.out.println(Thread.currentThread().getName() + "我是方式二");
        }
    };
    Thread thread = new Thread(runnable);
    thread.start();
}
方式三
public class p10 {
    public static void main(String[] args) {
        Thread thread = new Thread(
                new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        System.out.println(Thread.currentThread().getName() + "我是方式三");
                    }
                }
                );
        thread.start();
    }
}
public class p10 {
    public static void main(String[] args) {
        new Thread(
                new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        System.out.println(Thread.currentThread().getName() + "我是方式三");
                    }
                }
                ).start();
    }
}

线程休眠

如果子线程中 出现异常 只能try...catch处理
Thread类是Runnable接口的 实现类
重写方法中的run方法
该方法没有抛出异常
所有Runnable接口的实现类(包括Thread类)
都不能在run方法中抛出异常 只能处理
package com.lanou3g.p02;

public class Demo11 {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(10);
            System.out.println(Thread.currentThread().getName() + "我是主线程" + i);

        }
    }
}
class MyThread1 implements Runnable{

    @Override
    public void run() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // TODO Auto-generated method stub
        for(int i = 0; i < 50; i++) {
            System.out.println(i);
        }
    }

}
public class Demo11 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(
                new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        for(int i = 0; i < 50; i++) {
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName() + i);
                        }
                    }
                }
                );
        thread.start();
    }
}
package com.lanou3g;
/*
 * 卖火车票问题
 */
public class Demo05 {
    public static void main(String[] args) {
        TiketsRunnable tRunnable = new TiketsRunnable();
        // 创建1条线程 这条线程会执行 run方法(这条线程的任务)
        Thread t1 = new Thread(tRunnable);
        Thread t2 = new Thread(tRunnable);
        Thread t3 = new Thread(tRunnable);
        // 开启三个线程
        t1.start();
        t2.start();
        t3.start();
    }
}
/* 同步锁(同步代码块 )
 * 锁可以是任意对象 要保证 锁的唯一 三个线程都使用的是同一把锁
 * synchronized(对象锁) {

   }
 */
class TiketsRunnable implements Runnable{
    // 声明50个票 保证票是共享数据 只new一次该类的对象
    private int tickets = 50;
    // 创建了对象锁 保证唯一
    // 卖票方法
    @Override
    public void run() {
        while(true) {
            // 锁只要保证对象唯一就可以 填this
            synchronized (this) {
                // 操作的共享数据的代码
                if(tickets > 0) {
                    // 线程休眠一会
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    // 有票就卖一张
                    System.out.println(Thread.currentThread().getName() + "--" + tickets);
                    // 减少一张
                    tickets--;
                }else {
                        // 没票 结束循环
                        break;
                }
            }
            // 让线程让出cpu的资源
            Thread.yield();
        }

    }
}

同步锁

线程 遇到锁 就进 进代码块(携带锁)
当线程 执行完代码块中的代码 就把锁返还
线程 没有遇到锁 会在同步代码块外等着 遇到锁才能进
public class Demo06 {
    public static void main(String[] args) {
        TiketsRunnable1 tRunnable1 = new TiketsRunnable1();
        // 创建1条线程 这条线程会执行 run方法(这条线程的任务)
        Thread t1 = new Thread(tRunnable1);
        Thread t2 = new Thread(tRunnable1);
        Thread t3 = new Thread(tRunnable1);
        // 开启三个线程
        t1.start();
        t2.start();
        t3.start();
    }
}
class TiketsRunnable1 implements Runnable{
    // 静态方法的 同步代码块的锁 可以使用本类 类名.class
    // 声明50个票 保证票是共享数据 只new一次该类的对象
    private int tickets = 50;
    // 创建了对象锁 保证唯一
    private Object obj = new Object();
    // 卖票方法
    @Override
    public void run() {
        while(true) {
            if (sellTickets()) {
                break;
            }
            // 让出cpu资源
            Thread.yield();
        }
    }

    // 操作共享数据的方法
    // 在方法中添加synchronized关键词 把方法变成 同步方法
    // 同步方法肯定有锁
    public synchronized boolean sellTickets() {
        // 操作的共享数据的代码
        if(tickets > 0) {
            // 线程休眠一会
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // 有票就卖一张
            System.out.println(Thread.currentThread().getName() + "--" + tickets);
            // 减少一张
            tickets--;
            return false;
        }else {
                // 没票 结束循环
            return true;
        }

    }   
}

死锁

死锁是由于争用资源而出现的问题,有两份资源,A线程,拿了一份,B线程也拿了一份,双方都需要对方手里的资源才能执行完自己的线程
而双方又不会主动让出自己的资源,而是拿着自己的资源等待另一份资源,由于两个线程没有完成自己的任务
所以不会释放自己的资源,双方一直等待 造成死锁问题

 模拟线程死锁
 1.需要两个锁对象(保证唯一)

public class Demo07 {
    public static void main(String[] args) {
        DieLockRunnable die = new DieLockRunnable();
        Thread t1 = new Thread(die);
        Thread t2 = new Thread(die);
        t1.start();
        t2.start();
    }
}
// A锁
class LockA{
// 构造方法私有化
    private LockA() {
    }
    // 定义一个常量 锁对象 不能修改(也不能创建)
    public static final LockA LOCK_A = new LockA();
}
// B锁
class LockB{
// 构造方法私有化
    private LockB() {   
    }
    public static final LockB LOCK_B = new LockB();
}
class DieLockRunnable implements Runnable{
    // 声明一个标记
    // 标记一个是先A后B
    //     一次是先B后A
    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("else...LOCK_B");
                    synchronized (LockA.LOCK_A) {
                        System.out.println("else...LOCK_A");
                    }
                }
            }
            isTrue = !isTrue;
        }
    }

}

jdk1.5锁

Lock 接口
使用locklock.lock();
try{
    写操作共享数据的代码
}finally{
    lock.unlock();
}
接口实现创建线程的好处:
1.避免了直接继承Thread类的局限性(避免单继承)
2.接口即插即用 减少类与类之间的联系(可以解耦)
package com.lanou3g.p02;

import java.util.concurrent.locks.ReentrantLock;

public class Demo15 {
    public static void main(String[] args) {
        Tickets tickets = new Tickets();
        Thread thread = new Thread(tickets);
        Thread thread2 = new Thread(tickets);
        Thread thread3 = new Thread(tickets);
        thread.start();
        thread2.start();
        thread3.start();
    }
}
class Tickets implements Runnable{
    private int tickets = 50;
    private ReentrantLock  ree = new ReentrantLock();
    @Override
    public void run() {
        while(true) {
            ree.lock();
            try {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if(tickets > 0) {
                    System.out.println(Thread.currentThread().getName() + " " + tickets);
                    tickets--;
                }else {
                    break;
                }
                }finally {
                    ree.unlock();
                }
                Thread.yield();
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值