快捷搜索: 王者荣耀 脱发

多线程中的经典例题---卖票

多线程中的经典例题—卖票

使用Runnable接口创建线程

使用Runnable接口创建线程的时候,可以直接创建一个接口,然后实现内部的run方法,最后让接口对象作为Thread线程类的构造器的一个参数;也可以写一个Runnable接口的实现类,然后实现Runnable接口内部的run方法,然后让这个实现类作为Thread线程类的构造器的一个参数,其实也即是间接的让Runnable接口作为Thread线程类的构造器的一个对象;这里用的是第二种方式,创建一个Runnable接口的实现类,然后让这个实现类作为Thread线程类的构造器的一个对象,如下图:

可以从JVM的层面上理解上面所说的多个线程共用一个ticket,所以ticket不用声明成是static静态变量这句话:因为在堆区中只创建了一个w3对象,并且每个线程启动的时候用的都是w3对象里的run方法,所以栈中只有一个run方法对应的栈帧,这个栈帧的局部变量表中也只有一个ticket成员变量,所有的线程启动的时候都会用到这个ticket成员变量。

把synchronized加到方法上,如下图:

上图的java代码如下:

package org.xzy;
class Window3 implements Runnable{
          
   
    private int ticket=100;
    Object obj=new Object();
    @Override
    public void run() {
          
   
        while(ticket>0) {
          
   
            show();
        }
    }
    public synchronized void show(){
          
   
        if(ticket>0) {
          
   //在同步代码块中一定要加上if(ticket>0)这个判断条件
            try {
          
   
                Thread.sleep(10);
            } catch (InterruptedException e) {
          
   
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+ticket);
            ticket--;
        }
    }
}
public class Test5 {
          
   
    public static void main(String[] args) {
          
   
        Window3 w3 = new Window3();
        Thread th1 = new Thread(w3,"窗口1");
        Thread th2 = new Thread(w3,"窗口2");
        Thread th3 = new Thread(w3,"窗口3");
        th1.start();
        th2.start();
        th3.start();
    }
}

无论是把synchronized关键字加到方法上还是不加到方法上,结果都一样,如下图:

使用Thread线程类的子类创建对象

创建一个类,让这个类继承Thread线程类,这个类就叫做Thread线程类的子类,然后重写这个子类中的run方法,创建这个子类的对象,其实也就相当于是创建Thread线程类的对象了,就相当于创建了一个线程,如下图:

上图的java代码如下:

package org.xzy;


public class Test7 {
          
   
    public static void main(String[] args) {
          
   
        Window5 w1=new Window5();
        Window5 w2=new Window5();
        Window5 w3=new Window5();
        w1.setName("窗口一");
        w2.setName("窗口二");
        w3.setName("窗口三");
        w1.start();
        w2.start();
        w3.start();
    }
}
class Window5 extends Thread{
          
   
    private static int ticket=100;
    @Override
    public void run() {
          
   
        while(ticket>0) {
          
   
            show();
        }
    }
    private static synchronized void show() {
          
   
        if(ticket>0) {
          
   
            try {
          
   
                Thread.sleep(100);
            } catch (InterruptedException e) {
          
   
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":卖票,票号为"+ticket);
            ticket--;
        }
    }
}

执行结果,如下图:

注意:只要是想创建线程类,那么肯定会直接或者间接地使用到Thread线程类去创建线程。

经验分享 程序员 微信小程序 职场和发展