java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:

总结:实现Runnable接口比继承Thread类更有优势:

1.因为java只能单继承,实现Runnable接口可以避免单继承的局限性

2.继承Thread类,多个线程不能处理或者共享同一个资源,但是实现Runnable接口可以处理同一个资源。

下面我们做个测试:验证下。车站的售票系统售票的例子,车站的各个售票口相当于各个线程,我们先使用第一种方法几继承Thread类的方式实现:

代码如下:

 

package com.lp.ecjtu.Thread;

/**

 * 

 * @author Administrator

 * 车站的售票系统售票的例子,车站的各个售票口相当于各个线程。

 * 

 */

public class TicketsThread  extends Thread{

    //用静态变量存放这100张票,这样就不会卖重复

    private  int tickets = 100;

    public void run(){

        while(true){

            if(tickets > 0){

                System.out.println(Thread.currentThread().getName()+"***sale***"+(--tickets));

            }

        }

    }

    /**

     * @param args

     */

    public static void main(String[] args) {

        // 不合理的买票程序,因为,不同线程都可以卖同一张票,

        //现实生活中不是这样的,窗口1买完第99张票,窗口2不可以卖了。

        TicketsThread t1 = new TicketsThread();

        TicketsThread t2 = new TicketsThread();

        TicketsThread t3 = new TicketsThread();

        t1.start();

        t2.start();

        t3.start();

    }



}

代码的原理图如下:

 

总结:不合理的卖票方法,不同线程都可以卖同一张票,现实生活中不是这样的,窗口1卖完99号票,窗口2就不可以再卖这张票了。

怎么解决呢?使用实现Runnable接口的方法就可以解决,代码如下:

 

 

public class TicketsRunnable implements Runnable {

    private int ticket=100;

    //Object obj = new Object();

    public TicketsRunnable(){

        System.out.println("*****************************");

    }

    @Override

    public void run() {

        // TODO Auto-generated method stub

        

        while(true){

            //synchronized(obj){  //同步代码块

                if(ticket > 0){//当线程0被调起的时候,当执行到这条判断语句的时候,线程1被调起抢了CPU资源,线程0进入冻结状态。

                    try {

                        Thread.sleep(100);//中断当前活跃的线程,或者执行的线程

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                    System.out.println(Thread.currentThread().getName()+"正在卖票"+ticket--);

                    //System.out.println(Thread.currentThread().getId());

                    //System.out.println(Thread.currentThread().getName());

                }

            //}

            

        }

    }



    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        TicketsRunnable runna = new TicketsRunnable();

        Thread t1 = new Thread(runna);

        Thread t2 = new Thread(runna);

        Thread t3 = new Thread(runna);

        t1.start();

        t2.start();

        t3.start();

    }



}

 

 

 

上面代码简单内存图理解如下:

总结:三个窗口再卖100张票,直到卖完,3个线程才停止。卖的票的号码没有重复,真正实现了现实生活中的卖票的效果。但是存在一个线程安全问题,通过测试运行发现,打印出了0,-1,-2等错票,多线程运行出现了安全问题,这就需要引入线程锁机制,下一篇博客详细的讲解怎样避免这一问题。

 

你可能感兴趣的:(thread)