黑马程序员java笔记之二-----多线程

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




java中实现多线程操作有两种手段,一种继承自Thread类,另一种是实现Runnable接口。

 一、继承Thread

    Thread类是在java.lang包中定义的,一个类只要继承了Thread类,此类就称为多线程实现类。在Thread子类中,必须明确地覆写Thread类中的run()方法,此方法为线程的主体。
 class MyThread extends Thread{    // 继承Thread类,作为线程的实现类
    private String name ;        // 表示线程的名称
    public MyThread(String name){
        this.name = name ;        // 通过构造方法配置name属性
    }
    public void run(){    // 覆写run()方法,作为线程 的操作主体
        for(int i=0;i<10;i++){
            System.out.println(name + "运行,i = " + i) ;
        }
    }
       }
     public class ThreadDemo01{
        public static void main(String args[]){
            MyThread mt1 = new MyThread("线程A ") ;     // 实例化对象
            MyThread mt2 = new MyThread("线程B ") ;     // 实例化对象
            mt1.run() ;    // 调用线程主体
            mt2.run() ;    // 调用线程主体
     }
}


二、实现Runnable接口,Runnable接口中只定义了,一个抽象方法。

       

class MyThread implements Runnable{    // 实现Runnable接口,作为线程的实现类
           private String name ;        // 表示线程的名称

        public MyThread(String name){
            this.name = name ;        // 通过构造方法配置name属性
        }
        public void run(){    // 覆写run()方法,作为线程 的操作主体
            for(int i=0;i<10;i++){
                System.out.println(name + "运行,i = " + i) ;
            }
        }
       }
        public class RunnableDemo01{
            public static void main(String args[]){
                 MyThread mt1 = new MyThread("线程A ") ;     // 实例化对象
                MyThread mt2 = new MyThread("线程B ") ;     // 实例化对象
                Thread t1 = new Thread(mt1) ;        // 实例化Thread类对象
                Thread t2 = new Thread(mt2) ;        // 实例化Thread类对象
                t1.start() ;    // 启动多线程
                t2.start() ;    // 启动多线程
        }
    }
三、线程间通信:   多个线程在操作同一个资源,但是操作的动作不同。等待唤醒机制:

class Apple
{
    String name;
    String color;
    boolean flag = false;
}
class Input implements Runnable
{
    private Apple r ;
    Input(Apple r)
    {
        this.r = r;
    }
    public void run()
    {
        int x = 0;
        while(true)
        {
            synchronized(r)
            {

                if(r.flag) //标志位,如果flag=true,那么说明已经有数据,线程等待
                    try{r.wait();}catch(Exception e){}
                if(x==0)
                {
                    r.name="a";
                    r.color="red";
                }
                else
                {
                    r.name="b";
                    r.color = "yellow";
                }
                x = (x+1)%2;
                r.flag = true;//修改标志位
                r.notify();//唤醒输出线程
            }
        }
    }
}

class Output implements Runnable
{
    private Apple r ;
    
    Output(Apple r)
    {
        this.r = r;
    }
    public void run()
    {
        while(true)
        {
            synchronized(r)
            {
                if(!r.flag)//如果线程的标志位flag=false,线程等待
                    try{r.wait();}catch(Exception e){}
                System.out.println(r.name+"...."+r.color);
                r.flag = false;
                r.notify();//唤醒输入线程
            }
        }
    }
}
class  InputOutputTest
{
    public static void main(String[] args)
    {
        Apple r = new Apple();

        Input in = new Input(r);
        Output out = new Output(r);

        Thread t1 = new Thread(in);
        Thread t2 = new Thread(out);

        t1.start();
        t2.start();
    }
}


总结:

      wait();notify();notifyALL();

      都使用在同步中,因为只有对持有监视器(锁)的线程操作。所以要使用在同步中个,因为只有同步才具有锁

为什么这些操作线程饿方法要定义Object类中呢?因为这些方法在操作同步线程时,都必须要标识他们所操作的线程只有的锁。只有在同一个锁上的被等待线程,可以被同一个锁notify唤醒。不可以对不同锁中的线程进行唤醒。也就说,等待和唤醒必须是同一个锁。而锁可以使任意对象个,所以可以被任意对象调用的方法定义object类中。

       终止线程只有一种,run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。特殊情况:当线程处于了冻结状态。就不会读取到标记。那么线程就不会结束。当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。Thread类提供该方法 interrupt();

四、关于run()和start()分析:

class MyThread extends Thread{
    public void run(){
        try {
            Thread.currentThread().sleep(3000);
        } catch (InterruptedException e) {
        }
        System.out.println("MyThread running");
    }
}
public class ThreadTest{
    public static void main(String argv[]) {
        MyThread t = new MyThread();
        t.run();
        t.start();
        System.out.println("Thread Test");
      }
}

总结:

代码分析过程:MyThread t = new MyThread();创建了一个线程。

t.run();调用MyThread对象的run方法。这是只有一个线程在运行就是主线程。当主线程执行到了run方法中的sleep(3000);时。这是主线程处于冻结状态。程序并没有任何执行。当3秒过后,主线程打印了  MyThread running。 run方法执行结束。

t.start();开启了t线程。有两种可能情况。

       第一种,主线程在只执行了t.start()后,还具有执行权,继续往下执行, 打印了Thread Test。主线程结束。

t线程获取执行权,调用自己的run方法。然后执行的sleep(3000);冻结3秒。3秒后,打印MyThread running t线程结束,整个程序结束。

      第二种,主线程执行到t.start();开启了t线程,t线程就直接获取到了执行权。就调用自己的run方法。指定到sleep(3000).t线程冻结3秒,这是t线程就是释放了执行权。那么主线程开始执行打印了Thread Test,主线程结束。

等到3秒后,t线程打印MyThread running ,然后t线程结束。 程序结束。

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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值