黑马程序员技术交流社区

标题: 【石家庄校区】10期 JavaSE(二),day06-线程、同步 [打印本页]

作者: 谁用了我的名字    时间: 2018-9-20 13:05
标题: 【石家庄校区】10期 JavaSE(二),day06-线程、同步
就业班JavaSE第二阶段第6天
day06 【线程、同步】
--线程
        Thread类
                获取线程的名称:
                        使用Thread类中的方法getName()
                                String getName()返回该线程的名称
       
        创建多线程程序的第一种方式:
                创建Thread类的子类
                步骤:
                        创建Thread类的子类
                        在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么),该run()方法的方法体就代表了线程需要完成的任务
                        创建Thread类的子类对象
                        调用Thread类中的方法start方法,java虚拟机调用该线程的run方法
                                void start()使该线程开始执行;java虚拟机调用该线程的run方法
                                结果是两个线程并发地执行;当前线程(main线程)和另外一个线程(创建的新线程,执行其run方法)
                                多次启动一个线程是非法的,特别是当线程已经结束执行后,不能再重新启动
                        Java程序属于抢占式调度,哪个线程的优先级高,哪个线程优先执行,同一个优先级,随机选择一个执行       
       
        创建多线程程序的第二种方法:       
                实现Runnable接口
               
                步骤:
                        创建一个Runnable接口的实现类
                        在实现类中重写Runnable接口的run方法,设置线程任务
                        创建一个Runnable接口的实现类对象
                        创建Thread类对象,构造方法中传递Runnable接口的实现类对象
                        调用Thread类中的start方法啊,开启新的线程执行run方法
        Thread和Runnable的区别:
       
       
        匿名内部类方式实现线程的创建:
                public class RunableImpTest02 {
                public static void main(String[] args) {
                        Runnable runnable = new Runnable() {
                                @Override
                                public void run() {
                                        for (int i = 0; i < 10; i++) {
                                                System.out.println(Thread.currentThread().getName()+"-->"+i);
                                        }
                                }
                        };
                        new Thread(runnable,"赵丽颖").start();


                        for (int i = 0; i < 10; i++) {
                                System.out.println(Thread.currentThread().getName()+"-->"+i);
                        }
                }
        }
                       
--线程安全
        解决线程安全问题的一种方案:
                使用同步代码块
                格式:
                        synchronized(锁对象){
                                可能会出现线程安全问题的代码(访问了共享数据的代码)
                        }
                注意:
                        通过代码块中的锁对象,可以使用任意的对象
                        但是必须保证多个线程使用的锁对象是同一个
                        锁对象作用:、
                                把同步代码块锁住,只让一个线程在同步代码块中执行
                同步技术的原理:
                        使用了一个锁对象叫同步锁,也叫对象锁,也叫对象监视器
                        同步中的线程,没有执行完毕不会释放锁,同步外的线程没有锁进不去同步
       
        解决线程安全问题的第二种方案:
                同步方法:
                步骤:
                        吧访问了共享数据的代码抽取出来,放到一个方法中
                        在方法上添加syncharonized修饰符
                格式:
                        修饰符 syncharonized 返回值类型 方法名(参数列表){
                                可能会出现线程安全问题的代码(访问了共享数据的代码)
                        }
                       
                        定义一个同步方法
                        同步方法也会把方法内部的代码锁住
                        只让一个线程执行
                        同步方法的锁对象是谁?
                        就是实现类对象:new RunnableImp()
                        也就是this
       
        解决线程安全问题的第三种方案:       
                Lock锁:
                        提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
                        public void lock() :加同步锁。
                        public void unlock() :释放同步锁。
                        步骤:
                                在成员位置创建一个ReentrantLock对象
                                在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
                                在可能会出现安全问题的代码后条用Lock接口中的方法unlock释放锁
                       
--线程状态
        NEW(新建): 线程刚被创建,但是并未启动。还没调用start方法。
       
        Runnable(可运行):线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。
       
        Blocked(锁阻塞):当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
       
        Waiting(无限等待):一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
       
       
        Timed Waiting(计时等待):同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。
               
        Teminated(被终止):因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
       
        Waiting(无限等待):
                public class WaitingTest {


                        public static void main(String[] args) {
                                //创建锁对象,保证锁唯一
                                Object obj = new Object();
                                //消费者买包子线程
                                new Thread(new Runnable() {
                                        @Override
                                        public void run() {
                                                System.out.println(Thread.currentThread().getName() + "告知老板买包子");
                                                //然后等待
                                                synchronized (obj) {
                                                        try {
                                                                obj.wait();
                                                        } catch (InterruptedException e) {
                                                                e.printStackTrace();
                                                        }
                                                        System.out.println(Thread.currentThread().getName() + "开始吃包子");
                                                }
                                        }
                                }, "顾客").start();


                                //老板卖包子
                                new Thread(new Runnable() {
                                        @Override
                                        public void run() {
                                                //老板做包子需要5秒
                                                try {
                                                        Thread.sleep(5000);
                                                } catch (InterruptedException e) {
                                                        e.printStackTrace();
                                                }
                                                //包子做好,唤醒顾客
                                                synchronized (obj) {
                                                        obj.notify();
                                                        System.out.println(Thread.currentThread().getName() + "告知顾客包子做好了");
                                                }
                                        }
                                }, "老板").start();
                        }
                }
               
       

















欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2