黑马程序员—多线程

                                             -------android培训java培训、期待与您交流! ----------

1.创建线程的方式
(1).第一种方式:继承Thread类
步骤:
a.定义类继承Thread类
b.重写Thread类中的run方法。(目的:将自定义代码存储在run方法中,让线程运行。)
c.调用线程的start方法,该方法有两个作用:启动线程、调用run方法
 
示例:
public   class   Ticket   extends   Thread{
      private   int   tick   = 100;
      public   void   run(){
              while (   tick >0){
                System.   out .println(Thread. currentThread().getName()+ "..." + tick --);
           }
     }
      public   static   void   main(String[] args) {
           Ticket t1 =   new   Ticket();
           Ticket t2 =   new   Ticket();
           t1.start();
           t2.start();
     }
}
(2).第二种方式:实现Runnable接口
步骤:
a.定义类实现Runnable接口
b.重写Runnable接口中的run方法
c.通过Thread类建立线程对象
d.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
e.调用Thread类的start方法开启线程并调用Runnable子类的run方法
 
示例:
public   class   Ticket   implements   Runnable{
      private   int   tick   = 100;
     
      public   void   run(){
              while (   tick >0){
                System.   out .println(Thread. currentThread().getName()+ "..." + tick --);
           }
     }
      public   static   void   main(String[] args) {
           Ticket t =   new   Ticket();
              new   Thread(t).start();
              new   Thread(t).start();
              new   Thread(t).start();
     }
}
2.两种创建方式的区别
(1).实现接口方式:避免了单继承的局限性。建议使用实现接口的方式。
 
(2).继承Thread:线程代码存放在Thread子类的run方法中。
   实现Runnable:线程代码存放在接口的子类的run方法中。
 
(3). 使用继承Thread类的方法来创建线程,多条线程之间无法共享线程类的实例变量。使用实现Runnable接口的方式,则可以共享实例变量(重点)。
 
(4).实现接口方式,如果要访问当前线程,必须要用Thread.currentThread()方法。而继承方式则不需要,直接this即可。
 
3.一些注意事项
(1).多线程的一个特性:随机性

(2).为什么要重写run方法?
Thread类用于描述线程。该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法。也就是说Thread类中的run方法,用于存储线程要运行的代码。如果不重写的话,Thread中本身的run方法没有什么内容,所以必须重写,使得它运行你自己定义的代码。

(3).线程都有自己的默认名称,为Thread-编号

(4)几个方法:static Thread currentThread():获取当前线程对象
getName():获取线程名称              设置线程名称:setName或者通过构造函数

(5).线程五种状态:新建、就绪、运行、阻塞、死亡

(6).不要对已经处于启动的线程再次调用start方法,否则会引起异常

(7).不要试图对一个已经死亡的线程调用start()方法使它重新启动,否则引起异常。
 
4.同步代码块
(1).解决安全问题的方法:同步代码块
格式:
synchronized(对象)
{
     同步内容
}
注:对象如同锁,持有锁的线程可以在同步中执行。没有持有锁的线程即使获得cpu的准许,也进不去。对象可以为 任何对象
(2).同步前提:
a.必须要有两个或两个以上的线程。
b.必须是多个线程使用同一个锁。
(3).优点:解决了多线程的安全问题。缺点:多个线程需要判断锁,消耗资源。
(4).如何去找安全问题?
a.明确哪些代码是多线程运行代码
b.明确共享数据
c.明确多线程运行代码中哪些语句是操作共享数据的
 
5.同步函数
(1).同步函数的锁是:this
(2).静态同步函数的锁不是:this。而是该方法所在类的字节码文件对象。类名.class。
(静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。类名.class。该类型是Class。)
 
6.线程间通讯
(1)其实就是多个线程在操纵同一个资源,但操作的的动作不同。
(2).等待唤醒机制:
a.wait()、notify()、notifyAll()都是用在 同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。
b.为什么这些操纵线程的方法要定义在Object中?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁。只有同一个锁上的被等待的线程,可以被同一个锁上的notify唤醒。不可以对不同锁上的线程进行唤醒。
因为锁是任意对象的,所以被这些对象调用的方法就放在Object中

7.JDK1.5的新特性
      1.5中提供了多线程的升级解决方案。将同步synchronized操作替换成了Lock操作。将Object中的wait()、notify()、notifyAll()替换成了Condition对象。该对象可以通过Lock锁进行获取。同时也实现了本方只唤醒对象的操作。
 
示例:
import   java.util.concurrent.locks.*;
class   Res {
      private   String   name ;
      private   String   sex ;
      private   boolean   flag   =   false ;
      private   final   Lock   lock   =   new   ReentrantLock();
      private   Condition   con_in   =   lock .newCondition();
      private   Condition   con_ou   =   lock .newCondition();
     
      public   void   set(String name, String sex)   throws   InterruptedException {
              lock .lock();
              try {
                   while   (   flag )
                        con_in .await();
                   this .   name   = name;
                   this .   sex   = sex;
                System.   out .println(Thread. currentThread().getName()+ "...输入..." +   this .   name   +   "..."   +   this .   sex );
                   flag   =   true ;
                   con_ou .signal();
           }   finally {
                   lock .unlock();
           }
           
     }
      public   void   out()   throws   InterruptedException{
              lock .lock();
              try {
                   while   (!   flag )
                        con_ou .await();
                System.   out .println(Thread. currentThread().getName()+ "........输出......." +   this .   name   +   "..."   +   this .   sex );
                   flag   =   false ;
                   con_in .signal();
           }   finally {
                   lock .unlock();
           }
     }
}
class   Iuput   implements   Runnable {
      private   Res   r ;
      private   int   x   = 0;
      public   Iuput(Res r) {
              this .   r   = r;
     }
      public   void   run() {
              try {
                   while   (   true ) {
                        if   (   x   == 0) {
                              r .set(   "richard" ,   "man" );
                     }   else   {
                              r .set(   "flora" ,   "woman" );
                     }
                        x   = (   x   + 1) % 2;
                }
           }   catch (InterruptedException e){
                
           }    
     }
}
class   Ontput   implements   Runnable {
      private   Res   r ;
      public   Ontput(Res r) {
              this .   r   = r;
     }
      public   void   run() {
              try {
                   while   (   true )
                        r .out();
           }   catch (InterruptedException e){
                
           }
     }
}
public   class   TestMain {
      public   static   void   main(String[] args) {
           Res r =   new   Res();
              new   Thread(   new   Iuput(r)).start();
              new   Thread(   new   Iuput(r)).start();
              new   Thread(   new   Ontput(r)).start();
              new   Thread(   new   Ontput(r)).start();
     }
}
 
8.如何停止线程?
     以前的stop()已经不能用了,唯一的方法就是使run()方法结束。
开启多线程运行,运行代码通常是循环结构。只要控制住循环就可以让run方法结束,即线程结束。
 
特殊情况:
     当线程处于冻结状态,就不会读取到标记,那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行时状态中来,这样就可以操作标记让线程结束。
 
Thread类中提供了该清除冻结的方法:interrupt()方法。
 
9.一些特殊方法
(1).join():当A线程执行到B线程的join方法时,A就会等待,等B执行完,A才会重新执行。
               该方法用来临时加入线程执行。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值