线程

进程 :正在运行的程序。

            进程是系统进行资源分配和调度的独立单位。

            每一个进程都要他自己的内存空间和系统资源。

 

 

 

线程 :一个进程中的一个任务或者一条执行路径。

            是程序的执行单元和执行路径。

 

多线程诞生的意义:

                                提高计算机CPU的使用率。

 

一、线程的创建

        线程的创建两种方法:

               1、继承Thread线程类

                                    

                                      extends Thread,覆写父类Thread类的run()方法,new线程对象通过JVM调用start()方法来调用run()方法来启动线程

 

 

               2、实现Runnable接口

 

                                    implements Runnable , 必须覆写Runnbale接口的run()方法,new线程对象,用Thread类来接收这个对象,再通过JVM调用start()方法来调用run()方法                                        来启动线程

 

 

          两种创建线程的方法的优缺点:

             一般开发中,我们用的比较多的是实现Runnable接口这种方式

                    1、Runnable接口更好的解决的Java单继承的局限性,不占继承名额

                    2、Runnable接口能更好的适合多个线程去对同一个资源进行处理的情况

                    Thread线程都是单独处理自己的tickets这个共同数据,而Runnable线程是共同处理tickets这一个资源

 

                    3、能够把线程同程序代码与数据有效的分离开,体现的程序的健壮性,更好的体现出面向对象的编程思想。

 

 

 

二、线程的控制

            1、线程休眠

                    public static void sleep(long millis)

 

            2、线程加入

                    public final void jion()

 

                    在很多情况下,主线程生成并启动了子线程,如果子线程要进行大量的耗时运算的时候,主线程往往将于子线程结束前结束,此时,如果主线程结束需要用到子线程的运算结果的时候,就需要用到join()方法,等待子线程结束后再结束主线程。

 

 

            3、线程礼让

                    public static void yield()

 

                    yield()的目的是将正在运行的线程变成可运行的状态,让线程优先级相同的其他线程能够获得运行的机会。因此使用yield()的目的是让具有相同优先级的线程之间能够适当的轮转执行。

 

            4、线程后台(守护线程)

                    pubic final void setDaemon(boolean on)

 

            5、线程中断

                    public final void stop()

                    public void interrupt()

 

            6、线程等待

 

                    wait()---->Object类中的方法

 

            7、线程唤醒

 

                    notify()      notifyAll()------->Object类中的方法

 

 

 

 

三、线程的同步

 

        线程同步的方法(三种):

 

                                1、同步代码块

                                    synchronized(锁对象){

                                        同步代码;

                                    }

 

                                    一般锁对象是this      或者是类对象 比如String.class    System.class   自己定义的类.class

 

 

                                2、同步方法

                                    public synchronized void 方法名(){

                                         同步代码;

                                    }

 

 

            实现Runnable接口的线程与继承Thread类的线程实现同步方法的差异:

            1、在Thread的子类中使用同步方法:

                                            同步方法中,默认的锁对象就是this,但是,在Thread的子类中,无法充当锁对象。

 

                                             解决方法:

                                                               在同步方法上加static修饰  

                                                                public synchronized static void 方法名(){}

                                                               此时,静态修饰的同步方法的锁对象不再是this ,而是当前类的类对象  即  当前类的类名 .class

 

              2、在Runnable的子类中使用同步方法:

 

                                            两种使用方法:

 

                                                             1、被静态static修饰的同步方法  锁对象---->当前类名 .class

 

                                                             2、普通的同步方法                    锁对象---->this

 

 

 

 

                总结:

                            线程同步中,尽管多个线程加锁的方式不用(同步代码块、同步方法、LOCK),加锁的代码不同,但是只要是锁对象一致,那么同一时间就只能执行一个线程,实现线程同步。

 

 

                               3、Lock锁

                  Lock锁是JDK1.5版本推出的。同步代码块和同步方法都是我们理解上的加锁和释放锁,但是Lock锁机制能够更加清晰的看出在哪里加锁和在哪里解锁的。

                  static Lock lock = new ReentrantLock();//实例化一个锁对象

                    lock.lock();//加锁

                    lock.unlock();//解锁

 

Lock锁的弊端:

            lock锁相当于是给所有的线程一把锁和仅仅一把钥匙,当前线程使用完资源后才能释放锁,把钥匙交给下一个等待的线程让他进入临界资源。一旦锁起来的同步代码中出现了问题,线程终止,则无法释放锁钥匙,其他线程也无法进入执行。

            同步方法和同步代码块的方式实现的同步时,是线程终止自动释放锁的。

            为了解决线程锁代码出现问题终止而导致其他线程无法运行,我们必须用try{}finally{}结构,在finally{}中执行释放锁的代码

            try{

                锁代码;

            }finally{

                lock.unlock();

            }

            

 

 

 

 

 

 

四、线程的生命周期

       

        创建   就绪   运行   阻塞   死亡

 

 

 

 

五、线程通信

        生产者与消费者问题

 

线程之间是根据锁对象调用wait()   notify() / notifyAll()方法实现通信过程的。

 

问题:

 

        1、为什么是锁对象调用wait()方法?

        2、wait()  notify()方法是定义在哪个类里的?为什么?

 

回答:

        

        1、两个线程之间的唯一联系就是锁对象,只有锁对象调用wait()方法,让当线程阻塞,变成就绪状态,而共享这个锁对象的其他线程仍然可以运行。

 

        2、wait()  notify()方法是定义在Object类中的。因为wait()  notify()方法的调用时锁对象,而锁对象可以是任意类型的,所以wait() notify() 需要定义在所有类的父类Object里,保证所有对象都能调用。

 

 

 

注意:wait()方法是从哪里等待,就会被从哪里唤醒,紧接着执行下面的代码。

 

 

线程休眠的两种方法的区别:

    

        能够让线程休眠的方法----->wait()等待方法     sleep()休眠方法

 

 

        wait() 处于等待 ,只能被其他线程唤醒

 

        wait(long timeout) 处于等待,超过一定毫秒值   自动被唤醒

 

        wait(long timeout)与sleep(long timeout)都可让线程休眠一段时间

 

        区别:

 

                wait()方法被调用时,当前线程会自动释放锁,当前线程阻塞,然后进入就绪状态,等待被唤醒运行,被唤醒前其他进程可以执行

 

                sleep()方法被调用时,不会自动释放锁 ,其他线程无法执行

 

 

 

 

 

五、线程池

 

        对线程的统一管理  创建  分发   回收   再利用   预留

 

        JDK5后  内置线程

 

 

public static ExecutorService newCachedThread() ------->带缓存的线程池

 

public static ExecutorService newFixedThread(int nThreads) ------>带初始容量的线程池

 

public static ExecutorService newSingleThreadExecutor() --------->带一个线程的线程池

 

 

获取一个线程池对象的方式:

    ExecutorService pool=Executors.newFixedThread(3);

添加线程

    pool.submit();

关闭线程池

    pool.shutdown();

 

 

 

六、创建线程的第三种方式

 

        实现Callable接口

 

只能在线程池中使用,不能独立的做为一个线程启动,只能借助线程池启动

 

实现Callable接口的线程类的作用:

 

        Callable接口只有一个call()方法,子类实现接口一定要覆写call()方法,此方法就是相当于run()方法

 

        call()方法是有返回值的,返回的是Future的对象 此对象可以调用get()方法,获得计算的返回值

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值