多线程基础学习二

Thread类

位置:位于java.lang包中

1.设置线程的优先级:

     setPriority(int i);参数为一个整数,有三个值:

     Thread.MAX_PRIORITY 最高优先级 10

     Thread.MIN_PRIORITY  最低优先级 1

     Thread.MORM_PRIORITY 一般优先级 5

注意:依据平台的不同,OS对优先级的处理方式不一样,而且划分等级也可能不一样,所以这种方式不能保证线程的执行顺序,不鼓励使用。

2.线程的状态发生和控制

   1.yield()方法,只要一个线程调用了.yield()方法,线程就立即放弃CPU的时间片,从运行状态直接进入可运行状态。

   2.阻塞态

     三种方法可以导致线程变成组赛态:

      A.等待数据输入,如I/O中一些read方法

      B.调用了Sleep()方法。休眠指定时间

      C.对另一个线程调用了join方法。如t2.join()。则表示当前线程要等到t2线程结束后,才会打破阻塞状态。

    相应的从阻塞状态到可运行状态:

       A.数据输入结束。

       B.Sleep()方法所有休眠时间到达

       C.知道t2线程结束

      

       注意:Sleep()方法会抛出InterruptedException,若果在run()的方法里面调用了则不能调用了Sleep,则不会抛出InterruptedException异常,

                 因为父类和runnable接口都没有抛出异常,根据子方法绝不能比父方法抛出更多的原则,所以必须用try .. catch处理。

                 join()方法可以说把两个线程合并成一个线程,它也会抛出一个InterruptedException的异常。

 

       3.线程同步

          当多个线程并发的访问同一个共享资源时,就有可能导致共享资源的原子操作分开执行,这样的话就会导致共享资源的数据不一样和不完整的情况,这种共享资源称之为临界资源

       解决问题的办法

       同步锁机制:

          1. 一个对象除了属性和方法,还有互斥锁,锁池,和等待队列。

          2.每个对象都有一把锁,如果把这边锁分配给一个线程,则在此线程使用期间,其他线程就不能获得这个锁资源了,直到这个线程释放了锁资源。

          3.锁,锁池,和等待队列是对象自有的,用来分配给线程使用的,简单的变量没有

         

        实现同步的关键字:synchronized

           1.可以用来修饰代码块和方法

              如:1.修饰方法,就是对当前对象加锁,也叫做内同步法

                       synchronized void m(){}

              

        总结:凡是进入执行此代码块的方法,都必须拿到此对象的锁,否则的进入阻塞状态(对象的锁池),拿到锁的线程执行完后会释放锁资源(OS分配)。

 

               2.修饰代码块,对‘对象’加锁,又叫做外同步法

                   如:

                      void m(){

                          synchronized (对象名) {}//这里也是对当前对象加锁和内同步法是一样的

                      }

              总结:外同步法比内同步法更加的灵活,可以对不同的对象加锁,内同步法只能对当前对象加锁。

 

            静态方法允许使用synchronized,但构造方法是不允许的,因为没有对象。

            由此我们总结在:Verctor和ArrayList两个集合

                Verctor是线程安全的,因为Verctor的每个方法都加了synchronized修饰的,所以是线程安全的,但性能不高。

                ArrayList是线程不安全,因为方法没有用synchronized修饰,为了线程安全,可以使用外同步法,如:

                         synchrnized (obj){

                              obj.add(aa);

                         }//同样可以实现代码块的线程安全

 

                注意:不使用线程安全的原因:加锁是需要消耗资源,cpu时间,自然的效率就降低了,所以对该加锁的需要加,不该加锁的不要加锁。

 

              线程状态图:

                   

 

 

      注意:

         1.notify()和notifyAll()方法纯粹是通知其他在等待队列中的线程,只是把它们唤醒,状态到池锁,它不会让线程放弃锁资源。

         2.拥有此对象的锁资源,进入其他对象的锁池是不会放弃自己拥有的对象锁资源,这也是造成死锁的原因。

 

     3.锁池状态:

        也是一种特殊的阻塞状态

         当拥有此对象的线程进入已经加锁的临界资源,又没有此对象的锁时,则线程就进入此对象的锁池,等待os调配,分配锁标记。

      4.等待队列

          也是一种特殊的阻塞

           当一个线程调用了对象的wait()方法,那么线程就会释放它拥有的所有的锁标记,并自动进入对象的等待队列,直到有另外一个线程调用对象的notify()和notifyAll(),则此线程才会从等待队列进入锁池,等待os分配锁标记。     

          

         

           

   

 

     

posted @ 2020-07-28 06:21  小窝蜗  阅读(77)  评论(0编辑  收藏  举报